14c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky/* 24c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * mxl111sf-i2c.c - driver for the MaxLinear MXL111SF 34c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * 44c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> 54c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * 64c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * This program is free software; you can redistribute it and/or modify 74c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * it under the terms of the GNU General Public License as published by 84c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * the Free Software Foundation; either version 2 of the License, or 94c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * (at your option) any later version. 104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * 114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * This program is distributed in the hope that it will be useful, 124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * but WITHOUT ANY WARRANTY; without even the implied warranty of 134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * GNU General Public License for more details. 154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * 164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * You should have received a copy of the GNU General Public License 174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * along with this program; if not, write to the Free Software 184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky */ 204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#include "mxl111sf-i2c.h" 224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#include "mxl111sf.h" 234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky/* SW-I2C ----------------------------------------------------------------- */ 254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define SW_I2C_ADDR 0x1a 274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define SW_I2C_EN 0x02 284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define SW_SCL_OUT 0x04 294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define SW_SDA_OUT 0x08 304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define SW_SDA_IN 0x04 314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define SW_I2C_BUSY_ADDR 0x2f 334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define SW_I2C_BUSY 0x02 344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state, 364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 byte) 374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int i, ret; 394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 data = 0; 404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("(0x%02x)", byte); 424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); 444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < 8; i++) { 484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0; 504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | data); 534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 554c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | data | SW_SCL_OUT); 584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | data); 634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* last bit was 0 so we need to release SDA */ 684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (!(byte & 1)) { 694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SDA_OUT); 714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* CLK high for ACK readback */ 764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); 824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* drop the CLK after getting ACK, SDA will go high right away */ 864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SDA_OUT); 884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 914c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (data & SW_SDA_IN) 924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = -EIO; 934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyfail: 944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state, 984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 *pbyte) 994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 1004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int i, ret; 1014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 byte = 0; 1024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 data = 0; 1034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("()"); 1054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky *pbyte = 0; 1074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SDA_OUT); 1104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < 8; i++) { 1144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | 1164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky SW_SCL_OUT | SW_SDA_OUT); 1174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); 1214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (data & SW_SDA_IN) 1254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky byte |= (0x80 >> i); 1264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SDA_OUT); 1294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 1324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky *pbyte = byte; 1334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyfail: 1344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 1354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 1364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_start(struct mxl111sf_state *state) 1384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 1394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int ret; 1404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("()"); 1424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 1454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SCL_OUT); 1504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN); /* start */ 1554c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_fail(ret); 1564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyfail: 1574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 1584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 1594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_stop(struct mxl111sf_state *state) 1614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 1624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int ret; 1634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("()"); 1654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN); /* stop */ 1684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SCL_OUT); 1734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 1784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 1824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_SCL_OUT | SW_SDA_OUT); 1834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_fail(ret); 1844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyfail: 1854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 1864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 1874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_ack(struct mxl111sf_state *state) 1894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 1904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int ret; 1914c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 b = 0; 1924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("()"); 1944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b); 1964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 1974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 1984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 1994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 2004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN); 2014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 2024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* pull SDA low */ 2054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 2064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SCL_OUT); 2074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 2084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 2114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SDA_OUT); 2124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_fail(ret); 2134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyfail: 2144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 2154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 2164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_nack(struct mxl111sf_state *state) 2184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 2194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int ret; 2204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("()"); 2224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* SDA high to signal last byte read from slave */ 2244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 2254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 2264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 2274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 2304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 0x10 | SW_I2C_EN | SW_SDA_OUT); 2314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_fail(ret); 2324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyfail: 2334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 2344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 2354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky/* ------------------------------------------------------------------------ */ 2374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state, 2394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky struct i2c_msg *msg) 2404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 2414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int i, ret; 2424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("()"); 2444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (msg->flags & I2C_M_RD) { 2464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_start(state); 2484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 2494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_bitbang_sendbyte(state, 2524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky (msg->addr << 1) | 0x01); 2534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) { 2544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_stop(state); 2554c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 2574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < msg->len; i++) { 2594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_bitbang_recvbyte(state, 2604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky &msg->buf[i]); 2614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) { 2624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_stop(state); 2634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 2654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (i < msg->len - 1) 2674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_ack(state); 2684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 2694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_nack(state); 2714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_stop(state); 2734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 2744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } else { 2774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_start(state); 2794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) 2804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_bitbang_sendbyte(state, 2834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky (msg->addr << 1) & 0xfe); 2844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) { 2854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_stop(state); 2864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 2884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < msg->len; i++) { 2904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_bitbang_sendbyte(state, 2914c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[i]); 2924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) { 2934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_stop(state); 2944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto fail; 2954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 2964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 2974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 2984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* FIXME: we only want to do this on the last transaction */ 2994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_stop(state); 3004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 3014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyfail: 3024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 3034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 3044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky/* HW-I2C ----------------------------------------------------------------- */ 3064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define USB_WRITE_I2C_CMD 0x99 3084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define USB_READ_I2C_CMD 0xdd 3094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define USB_END_I2C_CMD 0xfe 3104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define USB_WRITE_I2C_CMD_LEN 26 3124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define USB_READ_I2C_CMD_LEN 24 3134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define I2C_MUX_REG 0x30 3154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define I2C_CONTROL_REG 0x00 3164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define I2C_SLAVE_ADDR_REG 0x08 3174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define I2C_DATA_REG 0x0c 3184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define I2C_INT_STATUS_REG 0x10 3194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_send_data(struct mxl111sf_state *state, 3214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 index, u8 *wdata) 3224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 3234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int ret = mxl111sf_ctrl_msg(state->d, wdata[0], 3244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky &wdata[1], 25, NULL, 0); 3254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_fail(ret); 3264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 3284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 3294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_get_data(struct mxl111sf_state *state, 3314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 index, u8 *wdata, u8 *rdata) 3324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 3334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int ret = mxl111sf_ctrl_msg(state->d, wdata[0], 3344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky &wdata[1], 25, rdata, 24); 3354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_fail(ret); 3364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 3384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 3394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state) 3414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 3424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 status = 0; 3434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 buf[26]; 3444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c_adv("()"); 3464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = USB_READ_I2C_CMD; 3484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 3494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_INT_STATUS_REG; 3514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x00; 3524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = 0x00; 3534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = USB_END_I2C_CMD; 3554c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_get_data(state, 0, buf, buf); 3574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (buf[1] & 0x04) 3594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky status = 1; 3604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return status; 3624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 3634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state) 3654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 3664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 status = 0; 3674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 buf[26]; 3684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("()"); 3704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = USB_READ_I2C_CMD; 3724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 3734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_MUX_REG; 3754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x00; 3764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = 0x00; 3774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = I2C_INT_STATUS_REG; 3794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[6] = 0x00; 3804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[7] = 0x00; 3814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[8] = USB_END_I2C_CMD; 3824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_get_data(state, 0, buf, buf); 3844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (0x08 == (buf[1] & 0x08)) 3864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky status = 1; 3874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if ((buf[5] & 0x02) == 0x02) 3894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */ 3904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3914c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return status; 3924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 3934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 3944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_readagain(struct mxl111sf_state *state, 3954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 count, u8 *rbuf) 3964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 3974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 i2c_w_data[26]; 3984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 i2c_r_data[24]; 3994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 i = 0; 4004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 fifo_status = 0; 4014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int status = 0; 4024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("read %d bytes", count); 4044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky while ((fifo_status == 0) && (i++ < 5)) 4064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky fifo_status = mxl111sf_i2c_check_fifo(state); 4074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_w_data[0] = 0xDD; 4094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_w_data[1] = 0x00; 4104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 2; i < 26; i++) 4124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_w_data[i] = 0xFE; 4134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < count; i++) { 4154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_w_data[2+(i*3)] = 0x0C; 4164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_w_data[3+(i*3)] = 0x00; 4174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_w_data[4+(i*3)] = 0x00; 4184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 4194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 420e836a1c078e230dd5a94bb086b186c2be3ec6a84Michael Krufky mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data); 4214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* Check for I2C NACK status */ 4234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl111sf_i2c_check_status(state) == 1) { 4244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("error!"); 4254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } else { 4264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < count; i++) { 4274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky rbuf[i] = i2c_r_data[(i*3)+1]; 4284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("%02x\t %02x", 4294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+1], 4304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+2]); 4314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 4324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky status = 1; 4344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 4354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return status; 4374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 4384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#define HWI2C400 1 4404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystatic int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state, 4414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky struct i2c_msg *msg) 4424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 4434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int i, k, ret = 0; 4444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u16 index = 0; 4454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 buf[26]; 4464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 i2c_r_data[24]; 4474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u16 block_len; 4484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u16 left_over_len; 4494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 rd_status[8]; 4504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 ret_status; 4514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky u8 readbuff[26]; 4524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d", 4544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0, 4554c4364e022f8422e602edbb97a2d873dc0b6c769Dan Carpenter (!(msg->flags & I2C_M_RD)) ? msg->len : 0); 4564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (index = 0; index < 26; index++) 4584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[index] = USB_END_I2C_CMD; 4594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* command to indicate data payload is destined for I2C interface */ 4614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = USB_WRITE_I2C_CMD; 4624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 4634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* enable I2C interface */ 4654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_MUX_REG; 4664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x80; 4674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = 0x00; 4684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* enable I2C interface */ 4704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = I2C_MUX_REG; 4714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[6] = 0x81; 4724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[7] = 0x00; 4734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* set Timeout register on I2C interface */ 4754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[8] = 0x14; 4764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[9] = 0xff; 4774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[10] = 0x00; 4784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#if 0 4794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* enable Interrupts on I2C interface */ 4804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[8] = 0x24; 4814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[9] = 0xF7; 4824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[10] = 0x00; 4834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky#endif 4844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[11] = 0x24; 4854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[12] = 0xF7; 4864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[13] = 0x00; 4874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_send_data(state, 0, buf); 4894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* write data on I2C bus */ 4914c4364e022f8422e602edbb97a2d873dc0b6c769Dan Carpenter if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) { 4924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("%d\t%02x", msg->len, msg->buf[0]); 4934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* control register on I2C interface to initialize I2C bus */ 4954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 4964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x5E; 4974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 4984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 4994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* I2C Slave device Address */ 5004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = I2C_SLAVE_ADDR_REG; 5014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[6] = (msg->addr); 5024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[7] = 0x00; 5034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[8] = USB_END_I2C_CMD; 5044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_send_data(state, 0, buf); 5054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* check for slave device status */ 5074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl111sf_i2c_check_status(state) == 1) { 5084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("NACK writing slave address %02x", 5094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->addr); 5104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* if NACK, stop I2C bus and exit */ 5114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 5124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x4E; 5134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 5144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = -EIO; 5154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto exit; 5164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* I2C interface can do I2C operations in block of 8 bytes of 5194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky I2C data. calculation to figure out number of blocks of i2c 5204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky data required to program */ 5214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky block_len = (msg->len / 8); 5224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky left_over_len = (msg->len % 8); 5234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky index = 0; 5244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("block_len %d, left_over_len %d", 5264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky block_len, left_over_len); 5274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (index = 0; index < block_len; index++) { 5294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < 8; i++) { 5304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* write data on I2C interface */ 5314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2+(i*3)] = I2C_DATA_REG; 5324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3+(i*3)] = msg->buf[(index*8)+i]; 5334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4+(i*3)] = 0x00; 5344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_send_data(state, 0, buf); 5374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* check for I2C NACK status */ 5394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl111sf_i2c_check_status(state) == 1) { 5404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("NACK writing slave address %02x", 5414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->addr); 5424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* if NACK, stop I2C bus and exit */ 5444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 5454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x4E; 5464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 5474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = -EIO; 5484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto exit; 5494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (left_over_len) { 5544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (k = 0; k < 26; k++) 5554c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[k] = USB_END_I2C_CMD; 5564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = 0x99; 5584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 5594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < left_over_len; i++) { 5614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2+(i*3)] = I2C_DATA_REG; 5624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3+(i*3)] = msg->buf[(index*8)+i]; 5634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("index = %d %d data %d", 5644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky index, i, msg->buf[(index*8)+i]); 5654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4+(i*3)] = 0x00; 5664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_send_data(state, 0, buf); 5684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* check for I2C NACK status */ 5704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl111sf_i2c_check_status(state) == 1) { 5714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("NACK writing slave address %02x", 5724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->addr); 5734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* if NACK, stop I2C bus and exit */ 5754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 5764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x4E; 5774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 5784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = -EIO; 5794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto exit; 5804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* issue I2C STOP after write */ 5854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 5864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x4E; 5874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 5884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 5904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5914c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* read data from I2C bus */ 5924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if ((msg->flags & I2C_M_RD) && (msg->len > 0)) { 5934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("read buf len %d", msg->len); 5944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 5954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* command to indicate data payload is 5964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky destined for I2C interface */ 5974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 5984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0xDF; 5994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 6004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* I2C xfer length */ 6024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = 0x14; 6034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[6] = (msg->len & 0xFF); 6044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[7] = 0; 6054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* I2C slave device Address */ 6074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[8] = I2C_SLAVE_ADDR_REG; 6084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[9] = msg->addr; 6094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[10] = 0x00; 6104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[11] = USB_END_I2C_CMD; 6114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_send_data(state, 0, buf); 6124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* check for I2C NACK status */ 6144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl111sf_i2c_check_status(state) == 1) { 6154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("NACK reading slave address %02x", 6164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->addr); 6174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* if NACK, stop I2C bus and exit */ 6194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 6204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0xC7; 6214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 6224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = -EIO; 6234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto exit; 6244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 6254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* I2C interface can do I2C operations in block of 8 bytes of 6274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky I2C data. calculation to figure out number of blocks of 6284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c data required to program */ 6294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky block_len = ((msg->len) / 8); 6304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky left_over_len = ((msg->len) % 8); 6314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky index = 0; 6324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("block_len %d, left_over_len %d", 6344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky block_len, left_over_len); 6354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* command to read data from I2C interface */ 6374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = USB_READ_I2C_CMD; 6384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 6394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (index = 0; index < block_len; index++) { 6414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* setup I2C read request packet on I2C interface */ 6424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < 8; i++) { 6434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2+(i*3)] = I2C_DATA_REG; 6444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3+(i*3)] = 0x00; 6454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4+(i*3)] = 0x00; 6464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 6474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data); 6494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* check for I2C NACK status */ 6514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl111sf_i2c_check_status(state) == 1) { 6524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("NACK reading slave address %02x", 6534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->addr); 6544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6554c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* if NACK, stop I2C bus and exit */ 6564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 6574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0xC7; 6584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 6594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = -EIO; 6604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto exit; 6614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 6624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* copy data from i2c data payload to read buffer */ 6644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < 8; i++) { 6654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky rd_status[i] = i2c_r_data[(i*3)+2]; 6664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (rd_status[i] == 0x04) { 6684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (i < 7) { 6694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("i2c fifo empty!" 6704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky " @ %d", i); 6714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[(index*8)+i] = 6724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+1]; 6734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* read again */ 6744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret_status = 6754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_readagain( 6764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky state, 8-(i+1), 6774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky readbuff); 6784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (ret_status == 1) { 6794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (k = 0; 6804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky k < 8-(i+1); 6814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky k++) { 6824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[(index*8)+(k+i+1)] = 6844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky readbuff[k]; 6854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("read data: %02x\t %02x", 6864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[(index*8)+(k+i)], 6874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky (index*8)+(k+i)); 6884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("read data: %02x\t %02x", 6894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[(index*8)+(k+i+1)], 6904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky readbuff[k]); 6914c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 6924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 6934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto stop_copy; 6944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } else { 6954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("readagain " 6964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky "ERROR!"); 6974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 6984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } else { 6994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[(index*8)+i] = 7004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+1]; 7014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } else { 7034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[(index*8)+i] = 7044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+1]; 7054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkystop_copy: 7084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ; 7094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (left_over_len) { 7134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (k = 0; k < 26; k++) 7144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[k] = USB_END_I2C_CMD; 7154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = 0xDD; 7174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 7184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < left_over_len; i++) { 7204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2+(i*3)] = I2C_DATA_REG; 7214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3+(i*3)] = 0x00; 7224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4+(i*3)] = 0x00; 7234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_get_data(state, 0, buf, 7254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data); 7264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* check for I2C NACK status */ 7284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl111sf_i2c_check_status(state) == 1) { 7294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("NACK reading slave address %02x", 7304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->addr); 7314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* if NACK, stop I2C bus and exit */ 7334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 7344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0xC7; 7354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 7364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = -EIO; 7374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky goto exit; 7384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < left_over_len; i++) { 7414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg->buf[(block_len*8)+i] = 7424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+1]; 7434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_i2c("read data: %02x\t %02x", 7444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+1], 7454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky i2c_r_data[(i*3)+2]); 7464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* indicate I2C interface to issue NACK 7504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky after next I2C read op */ 7514c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = USB_WRITE_I2C_CMD; 7524c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 7534c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7544c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* control register */ 7554c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 7564c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x17; 7574c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 7584c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7594c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = USB_END_I2C_CMD; 7604c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = mxl111sf_i2c_send_data(state, 0, buf); 7614c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7624c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* control register */ 7634c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 7644c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0xC7; 7654c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = (HWI2C400) ? 0x03 : 0x0D; 7664c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7674c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 7684c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyexit: 7694c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* STOP and disable I2C MUX */ 7704c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[0] = USB_WRITE_I2C_CMD; 7714c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[1] = 0x00; 7724c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7734c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* de-initilize I2C BUS */ 7744c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = USB_END_I2C_CMD; 7754c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_send_data(state, 0, buf); 7764c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7774c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* Control Register */ 7784c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_CONTROL_REG; 7794c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0xDF; 7804c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = 0x03; 7814c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7824c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* disable I2C interface */ 7834c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = I2C_MUX_REG; 7844c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[6] = 0x00; 7854c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[7] = 0x00; 7864c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7874c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* de-initilize I2C BUS */ 7884c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[8] = USB_END_I2C_CMD; 7894c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_send_data(state, 0, buf); 7904c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7914c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* disable I2C interface */ 7924c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[2] = I2C_MUX_REG; 7934c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[3] = 0x81; 7944c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[4] = 0x00; 7954c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 7964c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* disable I2C interface */ 7974c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[5] = I2C_MUX_REG; 7984c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[6] = 0x00; 7994c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[7] = 0x00; 8004c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8014c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky /* disable I2C interface */ 8024c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[8] = I2C_MUX_REG; 8034c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[9] = 0x00; 8044c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[10] = 0x00; 8054c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8064c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky buf[11] = USB_END_I2C_CMD; 8074c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_send_data(state, 0, buf); 8084c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8094c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return ret; 8104c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 8114c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8124c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky/* ------------------------------------------------------------------------ */ 8134c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8144c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufkyint mxl111sf_i2c_xfer(struct i2c_adapter *adap, 8154c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky struct i2c_msg msg[], int num) 8164c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky{ 8174c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky struct dvb_usb_device *d = i2c_get_adapdata(adap); 8184c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky struct mxl111sf_state *state = d->priv; 8194c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int hwi2c = (state->chip_rev > MXL111SF_V6); 8204c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky int i, ret; 8214c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8224c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 8234c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return -EAGAIN; 8244c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8254c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky for (i = 0; i < num; i++) { 8264c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky ret = (hwi2c) ? 8274c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) : 8284c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl111sf_i2c_sw_xfer_msg(state, &msg[i]); 8294c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky if (mxl_fail(ret)) { 8304c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mxl_debug_adv("failed with error %d on i2c " 8314c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky "transaction %d of %d, %sing %d bytes " 8324c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky "to/from 0x%02x", ret, i+1, num, 8334c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky (msg[i].flags & I2C_M_RD) ? 8344c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky "read" : "writ", 8354c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky msg[i].len, msg[i].addr); 8364c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8374c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky break; 8384c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 8394c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky } 8404c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8414c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky mutex_unlock(&d->i2c_mutex); 8424c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8434c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky return i == num ? num : -EREMOTEIO; 8444c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky} 8454c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky 8464c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky/* 8474c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * Local variables: 8484c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * c-basic-offset: 8 8494c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky * End: 8504c66c9205c0788e18eb09d482461aa2f551ee046Michael Krufky */ 851