1*786baecfSMauro Carvalho Chehab /* 2*786baecfSMauro Carvalho Chehab * mxl111sf-i2c.c - driver for the MaxLinear MXL111SF 3*786baecfSMauro Carvalho Chehab * 4*786baecfSMauro Carvalho Chehab * Copyright (C) 2010 Michael Krufky <mkrufky@kernellabs.com> 5*786baecfSMauro Carvalho Chehab * 6*786baecfSMauro Carvalho Chehab * This program is free software; you can redistribute it and/or modify 7*786baecfSMauro Carvalho Chehab * it under the terms of the GNU General Public License as published by 8*786baecfSMauro Carvalho Chehab * the Free Software Foundation; either version 2 of the License, or 9*786baecfSMauro Carvalho Chehab * (at your option) any later version. 10*786baecfSMauro Carvalho Chehab * 11*786baecfSMauro Carvalho Chehab * This program is distributed in the hope that it will be useful, 12*786baecfSMauro Carvalho Chehab * but WITHOUT ANY WARRANTY; without even the implied warranty of 13*786baecfSMauro Carvalho Chehab * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*786baecfSMauro Carvalho Chehab * GNU General Public License for more details. 15*786baecfSMauro Carvalho Chehab * 16*786baecfSMauro Carvalho Chehab * You should have received a copy of the GNU General Public License 17*786baecfSMauro Carvalho Chehab * along with this program; if not, write to the Free Software 18*786baecfSMauro Carvalho Chehab * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*786baecfSMauro Carvalho Chehab */ 20*786baecfSMauro Carvalho Chehab 21*786baecfSMauro Carvalho Chehab #include "mxl111sf-i2c.h" 22*786baecfSMauro Carvalho Chehab #include "mxl111sf.h" 23*786baecfSMauro Carvalho Chehab 24*786baecfSMauro Carvalho Chehab /* SW-I2C ----------------------------------------------------------------- */ 25*786baecfSMauro Carvalho Chehab 26*786baecfSMauro Carvalho Chehab #define SW_I2C_ADDR 0x1a 27*786baecfSMauro Carvalho Chehab #define SW_I2C_EN 0x02 28*786baecfSMauro Carvalho Chehab #define SW_SCL_OUT 0x04 29*786baecfSMauro Carvalho Chehab #define SW_SDA_OUT 0x08 30*786baecfSMauro Carvalho Chehab #define SW_SDA_IN 0x04 31*786baecfSMauro Carvalho Chehab 32*786baecfSMauro Carvalho Chehab #define SW_I2C_BUSY_ADDR 0x2f 33*786baecfSMauro Carvalho Chehab #define SW_I2C_BUSY 0x02 34*786baecfSMauro Carvalho Chehab 35*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_bitbang_sendbyte(struct mxl111sf_state *state, 36*786baecfSMauro Carvalho Chehab u8 byte) 37*786baecfSMauro Carvalho Chehab { 38*786baecfSMauro Carvalho Chehab int i, ret; 39*786baecfSMauro Carvalho Chehab u8 data = 0; 40*786baecfSMauro Carvalho Chehab 41*786baecfSMauro Carvalho Chehab mxl_i2c("(0x%02x)", byte); 42*786baecfSMauro Carvalho Chehab 43*786baecfSMauro Carvalho Chehab ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); 44*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 45*786baecfSMauro Carvalho Chehab goto fail; 46*786baecfSMauro Carvalho Chehab 47*786baecfSMauro Carvalho Chehab for (i = 0; i < 8; i++) { 48*786baecfSMauro Carvalho Chehab 49*786baecfSMauro Carvalho Chehab data = (byte & (0x80 >> i)) ? SW_SDA_OUT : 0; 50*786baecfSMauro Carvalho Chehab 51*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 52*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | data); 53*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 54*786baecfSMauro Carvalho Chehab goto fail; 55*786baecfSMauro Carvalho Chehab 56*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 57*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | data | SW_SCL_OUT); 58*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 59*786baecfSMauro Carvalho Chehab goto fail; 60*786baecfSMauro Carvalho Chehab 61*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 62*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | data); 63*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 64*786baecfSMauro Carvalho Chehab goto fail; 65*786baecfSMauro Carvalho Chehab } 66*786baecfSMauro Carvalho Chehab 67*786baecfSMauro Carvalho Chehab /* last bit was 0 so we need to release SDA */ 68*786baecfSMauro Carvalho Chehab if (!(byte & 1)) { 69*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 70*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SDA_OUT); 71*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 72*786baecfSMauro Carvalho Chehab goto fail; 73*786baecfSMauro Carvalho Chehab } 74*786baecfSMauro Carvalho Chehab 75*786baecfSMauro Carvalho Chehab /* CLK high for ACK readback */ 76*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 77*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 78*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 79*786baecfSMauro Carvalho Chehab goto fail; 80*786baecfSMauro Carvalho Chehab 81*786baecfSMauro Carvalho Chehab ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); 82*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 83*786baecfSMauro Carvalho Chehab goto fail; 84*786baecfSMauro Carvalho Chehab 85*786baecfSMauro Carvalho Chehab /* drop the CLK after getting ACK, SDA will go high right away */ 86*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 87*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SDA_OUT); 88*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 89*786baecfSMauro Carvalho Chehab goto fail; 90*786baecfSMauro Carvalho Chehab 91*786baecfSMauro Carvalho Chehab if (data & SW_SDA_IN) 92*786baecfSMauro Carvalho Chehab ret = -EIO; 93*786baecfSMauro Carvalho Chehab fail: 94*786baecfSMauro Carvalho Chehab return ret; 95*786baecfSMauro Carvalho Chehab } 96*786baecfSMauro Carvalho Chehab 97*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_bitbang_recvbyte(struct mxl111sf_state *state, 98*786baecfSMauro Carvalho Chehab u8 *pbyte) 99*786baecfSMauro Carvalho Chehab { 100*786baecfSMauro Carvalho Chehab int i, ret; 101*786baecfSMauro Carvalho Chehab u8 byte = 0; 102*786baecfSMauro Carvalho Chehab u8 data = 0; 103*786baecfSMauro Carvalho Chehab 104*786baecfSMauro Carvalho Chehab mxl_i2c("()"); 105*786baecfSMauro Carvalho Chehab 106*786baecfSMauro Carvalho Chehab *pbyte = 0; 107*786baecfSMauro Carvalho Chehab 108*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 109*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SDA_OUT); 110*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 111*786baecfSMauro Carvalho Chehab goto fail; 112*786baecfSMauro Carvalho Chehab 113*786baecfSMauro Carvalho Chehab for (i = 0; i < 8; i++) { 114*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 115*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | 116*786baecfSMauro Carvalho Chehab SW_SCL_OUT | SW_SDA_OUT); 117*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 118*786baecfSMauro Carvalho Chehab goto fail; 119*786baecfSMauro Carvalho Chehab 120*786baecfSMauro Carvalho Chehab ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &data); 121*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 122*786baecfSMauro Carvalho Chehab goto fail; 123*786baecfSMauro Carvalho Chehab 124*786baecfSMauro Carvalho Chehab if (data & SW_SDA_IN) 125*786baecfSMauro Carvalho Chehab byte |= (0x80 >> i); 126*786baecfSMauro Carvalho Chehab 127*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 128*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SDA_OUT); 129*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 130*786baecfSMauro Carvalho Chehab goto fail; 131*786baecfSMauro Carvalho Chehab } 132*786baecfSMauro Carvalho Chehab *pbyte = byte; 133*786baecfSMauro Carvalho Chehab fail: 134*786baecfSMauro Carvalho Chehab return ret; 135*786baecfSMauro Carvalho Chehab } 136*786baecfSMauro Carvalho Chehab 137*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_start(struct mxl111sf_state *state) 138*786baecfSMauro Carvalho Chehab { 139*786baecfSMauro Carvalho Chehab int ret; 140*786baecfSMauro Carvalho Chehab 141*786baecfSMauro Carvalho Chehab mxl_i2c("()"); 142*786baecfSMauro Carvalho Chehab 143*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 144*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 145*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 146*786baecfSMauro Carvalho Chehab goto fail; 147*786baecfSMauro Carvalho Chehab 148*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 149*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SCL_OUT); 150*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 151*786baecfSMauro Carvalho Chehab goto fail; 152*786baecfSMauro Carvalho Chehab 153*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 154*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN); /* start */ 155*786baecfSMauro Carvalho Chehab mxl_fail(ret); 156*786baecfSMauro Carvalho Chehab fail: 157*786baecfSMauro Carvalho Chehab return ret; 158*786baecfSMauro Carvalho Chehab } 159*786baecfSMauro Carvalho Chehab 160*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_stop(struct mxl111sf_state *state) 161*786baecfSMauro Carvalho Chehab { 162*786baecfSMauro Carvalho Chehab int ret; 163*786baecfSMauro Carvalho Chehab 164*786baecfSMauro Carvalho Chehab mxl_i2c("()"); 165*786baecfSMauro Carvalho Chehab 166*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 167*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN); /* stop */ 168*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 169*786baecfSMauro Carvalho Chehab goto fail; 170*786baecfSMauro Carvalho Chehab 171*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 172*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SCL_OUT); 173*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 174*786baecfSMauro Carvalho Chehab goto fail; 175*786baecfSMauro Carvalho Chehab 176*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 177*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 178*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 179*786baecfSMauro Carvalho Chehab goto fail; 180*786baecfSMauro Carvalho Chehab 181*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 182*786baecfSMauro Carvalho Chehab 0x10 | SW_SCL_OUT | SW_SDA_OUT); 183*786baecfSMauro Carvalho Chehab mxl_fail(ret); 184*786baecfSMauro Carvalho Chehab fail: 185*786baecfSMauro Carvalho Chehab return ret; 186*786baecfSMauro Carvalho Chehab } 187*786baecfSMauro Carvalho Chehab 188*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_ack(struct mxl111sf_state *state) 189*786baecfSMauro Carvalho Chehab { 190*786baecfSMauro Carvalho Chehab int ret; 191*786baecfSMauro Carvalho Chehab u8 b = 0; 192*786baecfSMauro Carvalho Chehab 193*786baecfSMauro Carvalho Chehab mxl_i2c("()"); 194*786baecfSMauro Carvalho Chehab 195*786baecfSMauro Carvalho Chehab ret = mxl111sf_read_reg(state, SW_I2C_BUSY_ADDR, &b); 196*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 197*786baecfSMauro Carvalho Chehab goto fail; 198*786baecfSMauro Carvalho Chehab 199*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 200*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN); 201*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 202*786baecfSMauro Carvalho Chehab goto fail; 203*786baecfSMauro Carvalho Chehab 204*786baecfSMauro Carvalho Chehab /* pull SDA low */ 205*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 206*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SCL_OUT); 207*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 208*786baecfSMauro Carvalho Chehab goto fail; 209*786baecfSMauro Carvalho Chehab 210*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 211*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SDA_OUT); 212*786baecfSMauro Carvalho Chehab mxl_fail(ret); 213*786baecfSMauro Carvalho Chehab fail: 214*786baecfSMauro Carvalho Chehab return ret; 215*786baecfSMauro Carvalho Chehab } 216*786baecfSMauro Carvalho Chehab 217*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_nack(struct mxl111sf_state *state) 218*786baecfSMauro Carvalho Chehab { 219*786baecfSMauro Carvalho Chehab int ret; 220*786baecfSMauro Carvalho Chehab 221*786baecfSMauro Carvalho Chehab mxl_i2c("()"); 222*786baecfSMauro Carvalho Chehab 223*786baecfSMauro Carvalho Chehab /* SDA high to signal last byte read from slave */ 224*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 225*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SCL_OUT | SW_SDA_OUT); 226*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 227*786baecfSMauro Carvalho Chehab goto fail; 228*786baecfSMauro Carvalho Chehab 229*786baecfSMauro Carvalho Chehab ret = mxl111sf_write_reg(state, SW_I2C_ADDR, 230*786baecfSMauro Carvalho Chehab 0x10 | SW_I2C_EN | SW_SDA_OUT); 231*786baecfSMauro Carvalho Chehab mxl_fail(ret); 232*786baecfSMauro Carvalho Chehab fail: 233*786baecfSMauro Carvalho Chehab return ret; 234*786baecfSMauro Carvalho Chehab } 235*786baecfSMauro Carvalho Chehab 236*786baecfSMauro Carvalho Chehab /* ------------------------------------------------------------------------ */ 237*786baecfSMauro Carvalho Chehab 238*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_sw_xfer_msg(struct mxl111sf_state *state, 239*786baecfSMauro Carvalho Chehab struct i2c_msg *msg) 240*786baecfSMauro Carvalho Chehab { 241*786baecfSMauro Carvalho Chehab int i, ret; 242*786baecfSMauro Carvalho Chehab 243*786baecfSMauro Carvalho Chehab mxl_i2c("()"); 244*786baecfSMauro Carvalho Chehab 245*786baecfSMauro Carvalho Chehab if (msg->flags & I2C_M_RD) { 246*786baecfSMauro Carvalho Chehab 247*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_start(state); 248*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 249*786baecfSMauro Carvalho Chehab goto fail; 250*786baecfSMauro Carvalho Chehab 251*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_bitbang_sendbyte(state, 252*786baecfSMauro Carvalho Chehab (msg->addr << 1) | 0x01); 253*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) { 254*786baecfSMauro Carvalho Chehab mxl111sf_i2c_stop(state); 255*786baecfSMauro Carvalho Chehab goto fail; 256*786baecfSMauro Carvalho Chehab } 257*786baecfSMauro Carvalho Chehab 258*786baecfSMauro Carvalho Chehab for (i = 0; i < msg->len; i++) { 259*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_bitbang_recvbyte(state, 260*786baecfSMauro Carvalho Chehab &msg->buf[i]); 261*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) { 262*786baecfSMauro Carvalho Chehab mxl111sf_i2c_stop(state); 263*786baecfSMauro Carvalho Chehab goto fail; 264*786baecfSMauro Carvalho Chehab } 265*786baecfSMauro Carvalho Chehab 266*786baecfSMauro Carvalho Chehab if (i < msg->len - 1) 267*786baecfSMauro Carvalho Chehab mxl111sf_i2c_ack(state); 268*786baecfSMauro Carvalho Chehab } 269*786baecfSMauro Carvalho Chehab 270*786baecfSMauro Carvalho Chehab mxl111sf_i2c_nack(state); 271*786baecfSMauro Carvalho Chehab 272*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_stop(state); 273*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 274*786baecfSMauro Carvalho Chehab goto fail; 275*786baecfSMauro Carvalho Chehab 276*786baecfSMauro Carvalho Chehab } else { 277*786baecfSMauro Carvalho Chehab 278*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_start(state); 279*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) 280*786baecfSMauro Carvalho Chehab goto fail; 281*786baecfSMauro Carvalho Chehab 282*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_bitbang_sendbyte(state, 283*786baecfSMauro Carvalho Chehab (msg->addr << 1) & 0xfe); 284*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) { 285*786baecfSMauro Carvalho Chehab mxl111sf_i2c_stop(state); 286*786baecfSMauro Carvalho Chehab goto fail; 287*786baecfSMauro Carvalho Chehab } 288*786baecfSMauro Carvalho Chehab 289*786baecfSMauro Carvalho Chehab for (i = 0; i < msg->len; i++) { 290*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_bitbang_sendbyte(state, 291*786baecfSMauro Carvalho Chehab msg->buf[i]); 292*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) { 293*786baecfSMauro Carvalho Chehab mxl111sf_i2c_stop(state); 294*786baecfSMauro Carvalho Chehab goto fail; 295*786baecfSMauro Carvalho Chehab } 296*786baecfSMauro Carvalho Chehab } 297*786baecfSMauro Carvalho Chehab 298*786baecfSMauro Carvalho Chehab /* FIXME: we only want to do this on the last transaction */ 299*786baecfSMauro Carvalho Chehab mxl111sf_i2c_stop(state); 300*786baecfSMauro Carvalho Chehab } 301*786baecfSMauro Carvalho Chehab fail: 302*786baecfSMauro Carvalho Chehab return ret; 303*786baecfSMauro Carvalho Chehab } 304*786baecfSMauro Carvalho Chehab 305*786baecfSMauro Carvalho Chehab /* HW-I2C ----------------------------------------------------------------- */ 306*786baecfSMauro Carvalho Chehab 307*786baecfSMauro Carvalho Chehab #define USB_WRITE_I2C_CMD 0x99 308*786baecfSMauro Carvalho Chehab #define USB_READ_I2C_CMD 0xdd 309*786baecfSMauro Carvalho Chehab #define USB_END_I2C_CMD 0xfe 310*786baecfSMauro Carvalho Chehab 311*786baecfSMauro Carvalho Chehab #define USB_WRITE_I2C_CMD_LEN 26 312*786baecfSMauro Carvalho Chehab #define USB_READ_I2C_CMD_LEN 24 313*786baecfSMauro Carvalho Chehab 314*786baecfSMauro Carvalho Chehab #define I2C_MUX_REG 0x30 315*786baecfSMauro Carvalho Chehab #define I2C_CONTROL_REG 0x00 316*786baecfSMauro Carvalho Chehab #define I2C_SLAVE_ADDR_REG 0x08 317*786baecfSMauro Carvalho Chehab #define I2C_DATA_REG 0x0c 318*786baecfSMauro Carvalho Chehab #define I2C_INT_STATUS_REG 0x10 319*786baecfSMauro Carvalho Chehab 320*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_send_data(struct mxl111sf_state *state, 321*786baecfSMauro Carvalho Chehab u8 index, u8 *wdata) 322*786baecfSMauro Carvalho Chehab { 323*786baecfSMauro Carvalho Chehab int ret = mxl111sf_ctrl_msg(state->d, wdata[0], 324*786baecfSMauro Carvalho Chehab &wdata[1], 25, NULL, 0); 325*786baecfSMauro Carvalho Chehab mxl_fail(ret); 326*786baecfSMauro Carvalho Chehab 327*786baecfSMauro Carvalho Chehab return ret; 328*786baecfSMauro Carvalho Chehab } 329*786baecfSMauro Carvalho Chehab 330*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_get_data(struct mxl111sf_state *state, 331*786baecfSMauro Carvalho Chehab u8 index, u8 *wdata, u8 *rdata) 332*786baecfSMauro Carvalho Chehab { 333*786baecfSMauro Carvalho Chehab int ret = mxl111sf_ctrl_msg(state->d, wdata[0], 334*786baecfSMauro Carvalho Chehab &wdata[1], 25, rdata, 24); 335*786baecfSMauro Carvalho Chehab mxl_fail(ret); 336*786baecfSMauro Carvalho Chehab 337*786baecfSMauro Carvalho Chehab return ret; 338*786baecfSMauro Carvalho Chehab } 339*786baecfSMauro Carvalho Chehab 340*786baecfSMauro Carvalho Chehab static u8 mxl111sf_i2c_check_status(struct mxl111sf_state *state) 341*786baecfSMauro Carvalho Chehab { 342*786baecfSMauro Carvalho Chehab u8 status = 0; 343*786baecfSMauro Carvalho Chehab u8 buf[26]; 344*786baecfSMauro Carvalho Chehab 345*786baecfSMauro Carvalho Chehab mxl_i2c_adv("()"); 346*786baecfSMauro Carvalho Chehab 347*786baecfSMauro Carvalho Chehab buf[0] = USB_READ_I2C_CMD; 348*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 349*786baecfSMauro Carvalho Chehab 350*786baecfSMauro Carvalho Chehab buf[2] = I2C_INT_STATUS_REG; 351*786baecfSMauro Carvalho Chehab buf[3] = 0x00; 352*786baecfSMauro Carvalho Chehab buf[4] = 0x00; 353*786baecfSMauro Carvalho Chehab 354*786baecfSMauro Carvalho Chehab buf[5] = USB_END_I2C_CMD; 355*786baecfSMauro Carvalho Chehab 356*786baecfSMauro Carvalho Chehab mxl111sf_i2c_get_data(state, 0, buf, buf); 357*786baecfSMauro Carvalho Chehab 358*786baecfSMauro Carvalho Chehab if (buf[1] & 0x04) 359*786baecfSMauro Carvalho Chehab status = 1; 360*786baecfSMauro Carvalho Chehab 361*786baecfSMauro Carvalho Chehab return status; 362*786baecfSMauro Carvalho Chehab } 363*786baecfSMauro Carvalho Chehab 364*786baecfSMauro Carvalho Chehab static u8 mxl111sf_i2c_check_fifo(struct mxl111sf_state *state) 365*786baecfSMauro Carvalho Chehab { 366*786baecfSMauro Carvalho Chehab u8 status = 0; 367*786baecfSMauro Carvalho Chehab u8 buf[26]; 368*786baecfSMauro Carvalho Chehab 369*786baecfSMauro Carvalho Chehab mxl_i2c("()"); 370*786baecfSMauro Carvalho Chehab 371*786baecfSMauro Carvalho Chehab buf[0] = USB_READ_I2C_CMD; 372*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 373*786baecfSMauro Carvalho Chehab 374*786baecfSMauro Carvalho Chehab buf[2] = I2C_MUX_REG; 375*786baecfSMauro Carvalho Chehab buf[3] = 0x00; 376*786baecfSMauro Carvalho Chehab buf[4] = 0x00; 377*786baecfSMauro Carvalho Chehab 378*786baecfSMauro Carvalho Chehab buf[5] = I2C_INT_STATUS_REG; 379*786baecfSMauro Carvalho Chehab buf[6] = 0x00; 380*786baecfSMauro Carvalho Chehab buf[7] = 0x00; 381*786baecfSMauro Carvalho Chehab buf[8] = USB_END_I2C_CMD; 382*786baecfSMauro Carvalho Chehab 383*786baecfSMauro Carvalho Chehab mxl111sf_i2c_get_data(state, 0, buf, buf); 384*786baecfSMauro Carvalho Chehab 385*786baecfSMauro Carvalho Chehab if (0x08 == (buf[1] & 0x08)) 386*786baecfSMauro Carvalho Chehab status = 1; 387*786baecfSMauro Carvalho Chehab 388*786baecfSMauro Carvalho Chehab if ((buf[5] & 0x02) == 0x02) 389*786baecfSMauro Carvalho Chehab mxl_i2c("(buf[5] & 0x02) == 0x02"); /* FIXME */ 390*786baecfSMauro Carvalho Chehab 391*786baecfSMauro Carvalho Chehab return status; 392*786baecfSMauro Carvalho Chehab } 393*786baecfSMauro Carvalho Chehab 394*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_readagain(struct mxl111sf_state *state, 395*786baecfSMauro Carvalho Chehab u8 count, u8 *rbuf) 396*786baecfSMauro Carvalho Chehab { 397*786baecfSMauro Carvalho Chehab u8 i2c_w_data[26]; 398*786baecfSMauro Carvalho Chehab u8 i2c_r_data[24]; 399*786baecfSMauro Carvalho Chehab u8 i = 0; 400*786baecfSMauro Carvalho Chehab u8 fifo_status = 0; 401*786baecfSMauro Carvalho Chehab int status = 0; 402*786baecfSMauro Carvalho Chehab 403*786baecfSMauro Carvalho Chehab mxl_i2c("read %d bytes", count); 404*786baecfSMauro Carvalho Chehab 405*786baecfSMauro Carvalho Chehab while ((fifo_status == 0) && (i++ < 5)) 406*786baecfSMauro Carvalho Chehab fifo_status = mxl111sf_i2c_check_fifo(state); 407*786baecfSMauro Carvalho Chehab 408*786baecfSMauro Carvalho Chehab i2c_w_data[0] = 0xDD; 409*786baecfSMauro Carvalho Chehab i2c_w_data[1] = 0x00; 410*786baecfSMauro Carvalho Chehab 411*786baecfSMauro Carvalho Chehab for (i = 2; i < 26; i++) 412*786baecfSMauro Carvalho Chehab i2c_w_data[i] = 0xFE; 413*786baecfSMauro Carvalho Chehab 414*786baecfSMauro Carvalho Chehab for (i = 0; i < count; i++) { 415*786baecfSMauro Carvalho Chehab i2c_w_data[2+(i*3)] = 0x0C; 416*786baecfSMauro Carvalho Chehab i2c_w_data[3+(i*3)] = 0x00; 417*786baecfSMauro Carvalho Chehab i2c_w_data[4+(i*3)] = 0x00; 418*786baecfSMauro Carvalho Chehab } 419*786baecfSMauro Carvalho Chehab 420*786baecfSMauro Carvalho Chehab mxl111sf_i2c_get_data(state, 0, i2c_w_data, i2c_r_data); 421*786baecfSMauro Carvalho Chehab 422*786baecfSMauro Carvalho Chehab /* Check for I2C NACK status */ 423*786baecfSMauro Carvalho Chehab if (mxl111sf_i2c_check_status(state) == 1) { 424*786baecfSMauro Carvalho Chehab mxl_i2c("error!"); 425*786baecfSMauro Carvalho Chehab } else { 426*786baecfSMauro Carvalho Chehab for (i = 0; i < count; i++) { 427*786baecfSMauro Carvalho Chehab rbuf[i] = i2c_r_data[(i*3)+1]; 428*786baecfSMauro Carvalho Chehab mxl_i2c("%02x\t %02x", 429*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+1], 430*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+2]); 431*786baecfSMauro Carvalho Chehab } 432*786baecfSMauro Carvalho Chehab 433*786baecfSMauro Carvalho Chehab status = 1; 434*786baecfSMauro Carvalho Chehab } 435*786baecfSMauro Carvalho Chehab 436*786baecfSMauro Carvalho Chehab return status; 437*786baecfSMauro Carvalho Chehab } 438*786baecfSMauro Carvalho Chehab 439*786baecfSMauro Carvalho Chehab #define HWI2C400 1 440*786baecfSMauro Carvalho Chehab static int mxl111sf_i2c_hw_xfer_msg(struct mxl111sf_state *state, 441*786baecfSMauro Carvalho Chehab struct i2c_msg *msg) 442*786baecfSMauro Carvalho Chehab { 443*786baecfSMauro Carvalho Chehab int i, k, ret = 0; 444*786baecfSMauro Carvalho Chehab u16 index = 0; 445*786baecfSMauro Carvalho Chehab u8 buf[26]; 446*786baecfSMauro Carvalho Chehab u8 i2c_r_data[24]; 447*786baecfSMauro Carvalho Chehab u16 block_len; 448*786baecfSMauro Carvalho Chehab u16 left_over_len; 449*786baecfSMauro Carvalho Chehab u8 rd_status[8]; 450*786baecfSMauro Carvalho Chehab u8 ret_status; 451*786baecfSMauro Carvalho Chehab u8 readbuff[26]; 452*786baecfSMauro Carvalho Chehab 453*786baecfSMauro Carvalho Chehab mxl_i2c("addr: 0x%02x, read buff len: %d, write buff len: %d", 454*786baecfSMauro Carvalho Chehab msg->addr, (msg->flags & I2C_M_RD) ? msg->len : 0, 455*786baecfSMauro Carvalho Chehab (!(msg->flags & I2C_M_RD)) ? msg->len : 0); 456*786baecfSMauro Carvalho Chehab 457*786baecfSMauro Carvalho Chehab for (index = 0; index < 26; index++) 458*786baecfSMauro Carvalho Chehab buf[index] = USB_END_I2C_CMD; 459*786baecfSMauro Carvalho Chehab 460*786baecfSMauro Carvalho Chehab /* command to indicate data payload is destined for I2C interface */ 461*786baecfSMauro Carvalho Chehab buf[0] = USB_WRITE_I2C_CMD; 462*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 463*786baecfSMauro Carvalho Chehab 464*786baecfSMauro Carvalho Chehab /* enable I2C interface */ 465*786baecfSMauro Carvalho Chehab buf[2] = I2C_MUX_REG; 466*786baecfSMauro Carvalho Chehab buf[3] = 0x80; 467*786baecfSMauro Carvalho Chehab buf[4] = 0x00; 468*786baecfSMauro Carvalho Chehab 469*786baecfSMauro Carvalho Chehab /* enable I2C interface */ 470*786baecfSMauro Carvalho Chehab buf[5] = I2C_MUX_REG; 471*786baecfSMauro Carvalho Chehab buf[6] = 0x81; 472*786baecfSMauro Carvalho Chehab buf[7] = 0x00; 473*786baecfSMauro Carvalho Chehab 474*786baecfSMauro Carvalho Chehab /* set Timeout register on I2C interface */ 475*786baecfSMauro Carvalho Chehab buf[8] = 0x14; 476*786baecfSMauro Carvalho Chehab buf[9] = 0xff; 477*786baecfSMauro Carvalho Chehab buf[10] = 0x00; 478*786baecfSMauro Carvalho Chehab #if 0 479*786baecfSMauro Carvalho Chehab /* enable Interrupts on I2C interface */ 480*786baecfSMauro Carvalho Chehab buf[8] = 0x24; 481*786baecfSMauro Carvalho Chehab buf[9] = 0xF7; 482*786baecfSMauro Carvalho Chehab buf[10] = 0x00; 483*786baecfSMauro Carvalho Chehab #endif 484*786baecfSMauro Carvalho Chehab buf[11] = 0x24; 485*786baecfSMauro Carvalho Chehab buf[12] = 0xF7; 486*786baecfSMauro Carvalho Chehab buf[13] = 0x00; 487*786baecfSMauro Carvalho Chehab 488*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_send_data(state, 0, buf); 489*786baecfSMauro Carvalho Chehab 490*786baecfSMauro Carvalho Chehab /* write data on I2C bus */ 491*786baecfSMauro Carvalho Chehab if (!(msg->flags & I2C_M_RD) && (msg->len > 0)) { 492*786baecfSMauro Carvalho Chehab mxl_i2c("%d\t%02x", msg->len, msg->buf[0]); 493*786baecfSMauro Carvalho Chehab 494*786baecfSMauro Carvalho Chehab /* control register on I2C interface to initialize I2C bus */ 495*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 496*786baecfSMauro Carvalho Chehab buf[3] = 0x5E; 497*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 498*786baecfSMauro Carvalho Chehab 499*786baecfSMauro Carvalho Chehab /* I2C Slave device Address */ 500*786baecfSMauro Carvalho Chehab buf[5] = I2C_SLAVE_ADDR_REG; 501*786baecfSMauro Carvalho Chehab buf[6] = (msg->addr); 502*786baecfSMauro Carvalho Chehab buf[7] = 0x00; 503*786baecfSMauro Carvalho Chehab buf[8] = USB_END_I2C_CMD; 504*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_send_data(state, 0, buf); 505*786baecfSMauro Carvalho Chehab 506*786baecfSMauro Carvalho Chehab /* check for slave device status */ 507*786baecfSMauro Carvalho Chehab if (mxl111sf_i2c_check_status(state) == 1) { 508*786baecfSMauro Carvalho Chehab mxl_i2c("NACK writing slave address %02x", 509*786baecfSMauro Carvalho Chehab msg->addr); 510*786baecfSMauro Carvalho Chehab /* if NACK, stop I2C bus and exit */ 511*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 512*786baecfSMauro Carvalho Chehab buf[3] = 0x4E; 513*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 514*786baecfSMauro Carvalho Chehab ret = -EIO; 515*786baecfSMauro Carvalho Chehab goto exit; 516*786baecfSMauro Carvalho Chehab } 517*786baecfSMauro Carvalho Chehab 518*786baecfSMauro Carvalho Chehab /* I2C interface can do I2C operations in block of 8 bytes of 519*786baecfSMauro Carvalho Chehab I2C data. calculation to figure out number of blocks of i2c 520*786baecfSMauro Carvalho Chehab data required to program */ 521*786baecfSMauro Carvalho Chehab block_len = (msg->len / 8); 522*786baecfSMauro Carvalho Chehab left_over_len = (msg->len % 8); 523*786baecfSMauro Carvalho Chehab index = 0; 524*786baecfSMauro Carvalho Chehab 525*786baecfSMauro Carvalho Chehab mxl_i2c("block_len %d, left_over_len %d", 526*786baecfSMauro Carvalho Chehab block_len, left_over_len); 527*786baecfSMauro Carvalho Chehab 528*786baecfSMauro Carvalho Chehab for (index = 0; index < block_len; index++) { 529*786baecfSMauro Carvalho Chehab for (i = 0; i < 8; i++) { 530*786baecfSMauro Carvalho Chehab /* write data on I2C interface */ 531*786baecfSMauro Carvalho Chehab buf[2+(i*3)] = I2C_DATA_REG; 532*786baecfSMauro Carvalho Chehab buf[3+(i*3)] = msg->buf[(index*8)+i]; 533*786baecfSMauro Carvalho Chehab buf[4+(i*3)] = 0x00; 534*786baecfSMauro Carvalho Chehab } 535*786baecfSMauro Carvalho Chehab 536*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_send_data(state, 0, buf); 537*786baecfSMauro Carvalho Chehab 538*786baecfSMauro Carvalho Chehab /* check for I2C NACK status */ 539*786baecfSMauro Carvalho Chehab if (mxl111sf_i2c_check_status(state) == 1) { 540*786baecfSMauro Carvalho Chehab mxl_i2c("NACK writing slave address %02x", 541*786baecfSMauro Carvalho Chehab msg->addr); 542*786baecfSMauro Carvalho Chehab 543*786baecfSMauro Carvalho Chehab /* if NACK, stop I2C bus and exit */ 544*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 545*786baecfSMauro Carvalho Chehab buf[3] = 0x4E; 546*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 547*786baecfSMauro Carvalho Chehab ret = -EIO; 548*786baecfSMauro Carvalho Chehab goto exit; 549*786baecfSMauro Carvalho Chehab } 550*786baecfSMauro Carvalho Chehab 551*786baecfSMauro Carvalho Chehab } 552*786baecfSMauro Carvalho Chehab 553*786baecfSMauro Carvalho Chehab if (left_over_len) { 554*786baecfSMauro Carvalho Chehab for (k = 0; k < 26; k++) 555*786baecfSMauro Carvalho Chehab buf[k] = USB_END_I2C_CMD; 556*786baecfSMauro Carvalho Chehab 557*786baecfSMauro Carvalho Chehab buf[0] = 0x99; 558*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 559*786baecfSMauro Carvalho Chehab 560*786baecfSMauro Carvalho Chehab for (i = 0; i < left_over_len; i++) { 561*786baecfSMauro Carvalho Chehab buf[2+(i*3)] = I2C_DATA_REG; 562*786baecfSMauro Carvalho Chehab buf[3+(i*3)] = msg->buf[(index*8)+i]; 563*786baecfSMauro Carvalho Chehab mxl_i2c("index = %d %d data %d", 564*786baecfSMauro Carvalho Chehab index, i, msg->buf[(index*8)+i]); 565*786baecfSMauro Carvalho Chehab buf[4+(i*3)] = 0x00; 566*786baecfSMauro Carvalho Chehab } 567*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_send_data(state, 0, buf); 568*786baecfSMauro Carvalho Chehab 569*786baecfSMauro Carvalho Chehab /* check for I2C NACK status */ 570*786baecfSMauro Carvalho Chehab if (mxl111sf_i2c_check_status(state) == 1) { 571*786baecfSMauro Carvalho Chehab mxl_i2c("NACK writing slave address %02x", 572*786baecfSMauro Carvalho Chehab msg->addr); 573*786baecfSMauro Carvalho Chehab 574*786baecfSMauro Carvalho Chehab /* if NACK, stop I2C bus and exit */ 575*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 576*786baecfSMauro Carvalho Chehab buf[3] = 0x4E; 577*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 578*786baecfSMauro Carvalho Chehab ret = -EIO; 579*786baecfSMauro Carvalho Chehab goto exit; 580*786baecfSMauro Carvalho Chehab } 581*786baecfSMauro Carvalho Chehab 582*786baecfSMauro Carvalho Chehab } 583*786baecfSMauro Carvalho Chehab 584*786baecfSMauro Carvalho Chehab /* issue I2C STOP after write */ 585*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 586*786baecfSMauro Carvalho Chehab buf[3] = 0x4E; 587*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 588*786baecfSMauro Carvalho Chehab 589*786baecfSMauro Carvalho Chehab } 590*786baecfSMauro Carvalho Chehab 591*786baecfSMauro Carvalho Chehab /* read data from I2C bus */ 592*786baecfSMauro Carvalho Chehab if ((msg->flags & I2C_M_RD) && (msg->len > 0)) { 593*786baecfSMauro Carvalho Chehab mxl_i2c("read buf len %d", msg->len); 594*786baecfSMauro Carvalho Chehab 595*786baecfSMauro Carvalho Chehab /* command to indicate data payload is 596*786baecfSMauro Carvalho Chehab destined for I2C interface */ 597*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 598*786baecfSMauro Carvalho Chehab buf[3] = 0xDF; 599*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 600*786baecfSMauro Carvalho Chehab 601*786baecfSMauro Carvalho Chehab /* I2C xfer length */ 602*786baecfSMauro Carvalho Chehab buf[5] = 0x14; 603*786baecfSMauro Carvalho Chehab buf[6] = (msg->len & 0xFF); 604*786baecfSMauro Carvalho Chehab buf[7] = 0; 605*786baecfSMauro Carvalho Chehab 606*786baecfSMauro Carvalho Chehab /* I2C slave device Address */ 607*786baecfSMauro Carvalho Chehab buf[8] = I2C_SLAVE_ADDR_REG; 608*786baecfSMauro Carvalho Chehab buf[9] = msg->addr; 609*786baecfSMauro Carvalho Chehab buf[10] = 0x00; 610*786baecfSMauro Carvalho Chehab buf[11] = USB_END_I2C_CMD; 611*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_send_data(state, 0, buf); 612*786baecfSMauro Carvalho Chehab 613*786baecfSMauro Carvalho Chehab /* check for I2C NACK status */ 614*786baecfSMauro Carvalho Chehab if (mxl111sf_i2c_check_status(state) == 1) { 615*786baecfSMauro Carvalho Chehab mxl_i2c("NACK reading slave address %02x", 616*786baecfSMauro Carvalho Chehab msg->addr); 617*786baecfSMauro Carvalho Chehab 618*786baecfSMauro Carvalho Chehab /* if NACK, stop I2C bus and exit */ 619*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 620*786baecfSMauro Carvalho Chehab buf[3] = 0xC7; 621*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 622*786baecfSMauro Carvalho Chehab ret = -EIO; 623*786baecfSMauro Carvalho Chehab goto exit; 624*786baecfSMauro Carvalho Chehab } 625*786baecfSMauro Carvalho Chehab 626*786baecfSMauro Carvalho Chehab /* I2C interface can do I2C operations in block of 8 bytes of 627*786baecfSMauro Carvalho Chehab I2C data. calculation to figure out number of blocks of 628*786baecfSMauro Carvalho Chehab i2c data required to program */ 629*786baecfSMauro Carvalho Chehab block_len = ((msg->len) / 8); 630*786baecfSMauro Carvalho Chehab left_over_len = ((msg->len) % 8); 631*786baecfSMauro Carvalho Chehab index = 0; 632*786baecfSMauro Carvalho Chehab 633*786baecfSMauro Carvalho Chehab mxl_i2c("block_len %d, left_over_len %d", 634*786baecfSMauro Carvalho Chehab block_len, left_over_len); 635*786baecfSMauro Carvalho Chehab 636*786baecfSMauro Carvalho Chehab /* command to read data from I2C interface */ 637*786baecfSMauro Carvalho Chehab buf[0] = USB_READ_I2C_CMD; 638*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 639*786baecfSMauro Carvalho Chehab 640*786baecfSMauro Carvalho Chehab for (index = 0; index < block_len; index++) { 641*786baecfSMauro Carvalho Chehab /* setup I2C read request packet on I2C interface */ 642*786baecfSMauro Carvalho Chehab for (i = 0; i < 8; i++) { 643*786baecfSMauro Carvalho Chehab buf[2+(i*3)] = I2C_DATA_REG; 644*786baecfSMauro Carvalho Chehab buf[3+(i*3)] = 0x00; 645*786baecfSMauro Carvalho Chehab buf[4+(i*3)] = 0x00; 646*786baecfSMauro Carvalho Chehab } 647*786baecfSMauro Carvalho Chehab 648*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_get_data(state, 0, buf, i2c_r_data); 649*786baecfSMauro Carvalho Chehab 650*786baecfSMauro Carvalho Chehab /* check for I2C NACK status */ 651*786baecfSMauro Carvalho Chehab if (mxl111sf_i2c_check_status(state) == 1) { 652*786baecfSMauro Carvalho Chehab mxl_i2c("NACK reading slave address %02x", 653*786baecfSMauro Carvalho Chehab msg->addr); 654*786baecfSMauro Carvalho Chehab 655*786baecfSMauro Carvalho Chehab /* if NACK, stop I2C bus and exit */ 656*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 657*786baecfSMauro Carvalho Chehab buf[3] = 0xC7; 658*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 659*786baecfSMauro Carvalho Chehab ret = -EIO; 660*786baecfSMauro Carvalho Chehab goto exit; 661*786baecfSMauro Carvalho Chehab } 662*786baecfSMauro Carvalho Chehab 663*786baecfSMauro Carvalho Chehab /* copy data from i2c data payload to read buffer */ 664*786baecfSMauro Carvalho Chehab for (i = 0; i < 8; i++) { 665*786baecfSMauro Carvalho Chehab rd_status[i] = i2c_r_data[(i*3)+2]; 666*786baecfSMauro Carvalho Chehab 667*786baecfSMauro Carvalho Chehab if (rd_status[i] == 0x04) { 668*786baecfSMauro Carvalho Chehab if (i < 7) { 669*786baecfSMauro Carvalho Chehab mxl_i2c("i2c fifo empty!" 670*786baecfSMauro Carvalho Chehab " @ %d", i); 671*786baecfSMauro Carvalho Chehab msg->buf[(index*8)+i] = 672*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+1]; 673*786baecfSMauro Carvalho Chehab /* read again */ 674*786baecfSMauro Carvalho Chehab ret_status = 675*786baecfSMauro Carvalho Chehab mxl111sf_i2c_readagain( 676*786baecfSMauro Carvalho Chehab state, 8-(i+1), 677*786baecfSMauro Carvalho Chehab readbuff); 678*786baecfSMauro Carvalho Chehab if (ret_status == 1) { 679*786baecfSMauro Carvalho Chehab for (k = 0; 680*786baecfSMauro Carvalho Chehab k < 8-(i+1); 681*786baecfSMauro Carvalho Chehab k++) { 682*786baecfSMauro Carvalho Chehab 683*786baecfSMauro Carvalho Chehab msg->buf[(index*8)+(k+i+1)] = 684*786baecfSMauro Carvalho Chehab readbuff[k]; 685*786baecfSMauro Carvalho Chehab mxl_i2c("read data: %02x\t %02x", 686*786baecfSMauro Carvalho Chehab msg->buf[(index*8)+(k+i)], 687*786baecfSMauro Carvalho Chehab (index*8)+(k+i)); 688*786baecfSMauro Carvalho Chehab mxl_i2c("read data: %02x\t %02x", 689*786baecfSMauro Carvalho Chehab msg->buf[(index*8)+(k+i+1)], 690*786baecfSMauro Carvalho Chehab readbuff[k]); 691*786baecfSMauro Carvalho Chehab 692*786baecfSMauro Carvalho Chehab } 693*786baecfSMauro Carvalho Chehab goto stop_copy; 694*786baecfSMauro Carvalho Chehab } else { 695*786baecfSMauro Carvalho Chehab mxl_i2c("readagain " 696*786baecfSMauro Carvalho Chehab "ERROR!"); 697*786baecfSMauro Carvalho Chehab } 698*786baecfSMauro Carvalho Chehab } else { 699*786baecfSMauro Carvalho Chehab msg->buf[(index*8)+i] = 700*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+1]; 701*786baecfSMauro Carvalho Chehab } 702*786baecfSMauro Carvalho Chehab } else { 703*786baecfSMauro Carvalho Chehab msg->buf[(index*8)+i] = 704*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+1]; 705*786baecfSMauro Carvalho Chehab } 706*786baecfSMauro Carvalho Chehab } 707*786baecfSMauro Carvalho Chehab stop_copy: 708*786baecfSMauro Carvalho Chehab ; 709*786baecfSMauro Carvalho Chehab 710*786baecfSMauro Carvalho Chehab } 711*786baecfSMauro Carvalho Chehab 712*786baecfSMauro Carvalho Chehab if (left_over_len) { 713*786baecfSMauro Carvalho Chehab for (k = 0; k < 26; k++) 714*786baecfSMauro Carvalho Chehab buf[k] = USB_END_I2C_CMD; 715*786baecfSMauro Carvalho Chehab 716*786baecfSMauro Carvalho Chehab buf[0] = 0xDD; 717*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 718*786baecfSMauro Carvalho Chehab 719*786baecfSMauro Carvalho Chehab for (i = 0; i < left_over_len; i++) { 720*786baecfSMauro Carvalho Chehab buf[2+(i*3)] = I2C_DATA_REG; 721*786baecfSMauro Carvalho Chehab buf[3+(i*3)] = 0x00; 722*786baecfSMauro Carvalho Chehab buf[4+(i*3)] = 0x00; 723*786baecfSMauro Carvalho Chehab } 724*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_get_data(state, 0, buf, 725*786baecfSMauro Carvalho Chehab i2c_r_data); 726*786baecfSMauro Carvalho Chehab 727*786baecfSMauro Carvalho Chehab /* check for I2C NACK status */ 728*786baecfSMauro Carvalho Chehab if (mxl111sf_i2c_check_status(state) == 1) { 729*786baecfSMauro Carvalho Chehab mxl_i2c("NACK reading slave address %02x", 730*786baecfSMauro Carvalho Chehab msg->addr); 731*786baecfSMauro Carvalho Chehab 732*786baecfSMauro Carvalho Chehab /* if NACK, stop I2C bus and exit */ 733*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 734*786baecfSMauro Carvalho Chehab buf[3] = 0xC7; 735*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 736*786baecfSMauro Carvalho Chehab ret = -EIO; 737*786baecfSMauro Carvalho Chehab goto exit; 738*786baecfSMauro Carvalho Chehab } 739*786baecfSMauro Carvalho Chehab 740*786baecfSMauro Carvalho Chehab for (i = 0; i < left_over_len; i++) { 741*786baecfSMauro Carvalho Chehab msg->buf[(block_len*8)+i] = 742*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+1]; 743*786baecfSMauro Carvalho Chehab mxl_i2c("read data: %02x\t %02x", 744*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+1], 745*786baecfSMauro Carvalho Chehab i2c_r_data[(i*3)+2]); 746*786baecfSMauro Carvalho Chehab } 747*786baecfSMauro Carvalho Chehab } 748*786baecfSMauro Carvalho Chehab 749*786baecfSMauro Carvalho Chehab /* indicate I2C interface to issue NACK 750*786baecfSMauro Carvalho Chehab after next I2C read op */ 751*786baecfSMauro Carvalho Chehab buf[0] = USB_WRITE_I2C_CMD; 752*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 753*786baecfSMauro Carvalho Chehab 754*786baecfSMauro Carvalho Chehab /* control register */ 755*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 756*786baecfSMauro Carvalho Chehab buf[3] = 0x17; 757*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 758*786baecfSMauro Carvalho Chehab 759*786baecfSMauro Carvalho Chehab buf[5] = USB_END_I2C_CMD; 760*786baecfSMauro Carvalho Chehab ret = mxl111sf_i2c_send_data(state, 0, buf); 761*786baecfSMauro Carvalho Chehab 762*786baecfSMauro Carvalho Chehab /* control register */ 763*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 764*786baecfSMauro Carvalho Chehab buf[3] = 0xC7; 765*786baecfSMauro Carvalho Chehab buf[4] = (HWI2C400) ? 0x03 : 0x0D; 766*786baecfSMauro Carvalho Chehab 767*786baecfSMauro Carvalho Chehab } 768*786baecfSMauro Carvalho Chehab exit: 769*786baecfSMauro Carvalho Chehab /* STOP and disable I2C MUX */ 770*786baecfSMauro Carvalho Chehab buf[0] = USB_WRITE_I2C_CMD; 771*786baecfSMauro Carvalho Chehab buf[1] = 0x00; 772*786baecfSMauro Carvalho Chehab 773*786baecfSMauro Carvalho Chehab /* de-initilize I2C BUS */ 774*786baecfSMauro Carvalho Chehab buf[5] = USB_END_I2C_CMD; 775*786baecfSMauro Carvalho Chehab mxl111sf_i2c_send_data(state, 0, buf); 776*786baecfSMauro Carvalho Chehab 777*786baecfSMauro Carvalho Chehab /* Control Register */ 778*786baecfSMauro Carvalho Chehab buf[2] = I2C_CONTROL_REG; 779*786baecfSMauro Carvalho Chehab buf[3] = 0xDF; 780*786baecfSMauro Carvalho Chehab buf[4] = 0x03; 781*786baecfSMauro Carvalho Chehab 782*786baecfSMauro Carvalho Chehab /* disable I2C interface */ 783*786baecfSMauro Carvalho Chehab buf[5] = I2C_MUX_REG; 784*786baecfSMauro Carvalho Chehab buf[6] = 0x00; 785*786baecfSMauro Carvalho Chehab buf[7] = 0x00; 786*786baecfSMauro Carvalho Chehab 787*786baecfSMauro Carvalho Chehab /* de-initilize I2C BUS */ 788*786baecfSMauro Carvalho Chehab buf[8] = USB_END_I2C_CMD; 789*786baecfSMauro Carvalho Chehab mxl111sf_i2c_send_data(state, 0, buf); 790*786baecfSMauro Carvalho Chehab 791*786baecfSMauro Carvalho Chehab /* disable I2C interface */ 792*786baecfSMauro Carvalho Chehab buf[2] = I2C_MUX_REG; 793*786baecfSMauro Carvalho Chehab buf[3] = 0x81; 794*786baecfSMauro Carvalho Chehab buf[4] = 0x00; 795*786baecfSMauro Carvalho Chehab 796*786baecfSMauro Carvalho Chehab /* disable I2C interface */ 797*786baecfSMauro Carvalho Chehab buf[5] = I2C_MUX_REG; 798*786baecfSMauro Carvalho Chehab buf[6] = 0x00; 799*786baecfSMauro Carvalho Chehab buf[7] = 0x00; 800*786baecfSMauro Carvalho Chehab 801*786baecfSMauro Carvalho Chehab /* disable I2C interface */ 802*786baecfSMauro Carvalho Chehab buf[8] = I2C_MUX_REG; 803*786baecfSMauro Carvalho Chehab buf[9] = 0x00; 804*786baecfSMauro Carvalho Chehab buf[10] = 0x00; 805*786baecfSMauro Carvalho Chehab 806*786baecfSMauro Carvalho Chehab buf[11] = USB_END_I2C_CMD; 807*786baecfSMauro Carvalho Chehab mxl111sf_i2c_send_data(state, 0, buf); 808*786baecfSMauro Carvalho Chehab 809*786baecfSMauro Carvalho Chehab return ret; 810*786baecfSMauro Carvalho Chehab } 811*786baecfSMauro Carvalho Chehab 812*786baecfSMauro Carvalho Chehab /* ------------------------------------------------------------------------ */ 813*786baecfSMauro Carvalho Chehab 814*786baecfSMauro Carvalho Chehab int mxl111sf_i2c_xfer(struct i2c_adapter *adap, 815*786baecfSMauro Carvalho Chehab struct i2c_msg msg[], int num) 816*786baecfSMauro Carvalho Chehab { 817*786baecfSMauro Carvalho Chehab struct dvb_usb_device *d = i2c_get_adapdata(adap); 818*786baecfSMauro Carvalho Chehab struct mxl111sf_state *state = d->priv; 819*786baecfSMauro Carvalho Chehab int hwi2c = (state->chip_rev > MXL111SF_V6); 820*786baecfSMauro Carvalho Chehab int i, ret; 821*786baecfSMauro Carvalho Chehab 822*786baecfSMauro Carvalho Chehab if (mutex_lock_interruptible(&d->i2c_mutex) < 0) 823*786baecfSMauro Carvalho Chehab return -EAGAIN; 824*786baecfSMauro Carvalho Chehab 825*786baecfSMauro Carvalho Chehab for (i = 0; i < num; i++) { 826*786baecfSMauro Carvalho Chehab ret = (hwi2c) ? 827*786baecfSMauro Carvalho Chehab mxl111sf_i2c_hw_xfer_msg(state, &msg[i]) : 828*786baecfSMauro Carvalho Chehab mxl111sf_i2c_sw_xfer_msg(state, &msg[i]); 829*786baecfSMauro Carvalho Chehab if (mxl_fail(ret)) { 830*786baecfSMauro Carvalho Chehab mxl_debug_adv("failed with error %d on i2c " 831*786baecfSMauro Carvalho Chehab "transaction %d of %d, %sing %d bytes " 832*786baecfSMauro Carvalho Chehab "to/from 0x%02x", ret, i+1, num, 833*786baecfSMauro Carvalho Chehab (msg[i].flags & I2C_M_RD) ? 834*786baecfSMauro Carvalho Chehab "read" : "writ", 835*786baecfSMauro Carvalho Chehab msg[i].len, msg[i].addr); 836*786baecfSMauro Carvalho Chehab 837*786baecfSMauro Carvalho Chehab break; 838*786baecfSMauro Carvalho Chehab } 839*786baecfSMauro Carvalho Chehab } 840*786baecfSMauro Carvalho Chehab 841*786baecfSMauro Carvalho Chehab mutex_unlock(&d->i2c_mutex); 842*786baecfSMauro Carvalho Chehab 843*786baecfSMauro Carvalho Chehab return i == num ? num : -EREMOTEIO; 844*786baecfSMauro Carvalho Chehab } 845*786baecfSMauro Carvalho Chehab 846*786baecfSMauro Carvalho Chehab /* 847*786baecfSMauro Carvalho Chehab * Local variables: 848*786baecfSMauro Carvalho Chehab * c-basic-offset: 8 849*786baecfSMauro Carvalho Chehab * End: 850*786baecfSMauro Carvalho Chehab */ 851