1 /* 2 * cobalt I2C functions 3 * 4 * Derived from cx18-i2c.c 5 * 6 * Copyright 2012-2015 Cisco Systems, Inc. and/or its affiliates. 7 * All rights reserved. 8 * 9 * This program is free software; you may redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; version 2 of the License. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 16 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 17 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 18 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 * SOFTWARE. 21 */ 22 23 #include "cobalt-driver.h" 24 #include "cobalt-i2c.h" 25 26 struct cobalt_i2c_regs { 27 /* Clock prescaler register lo-byte */ 28 u8 prerlo; 29 u8 dummy0[3]; 30 /* Clock prescaler register high-byte */ 31 u8 prerhi; 32 u8 dummy1[3]; 33 /* Control register */ 34 u8 ctr; 35 u8 dummy2[3]; 36 /* Transmit/Receive register */ 37 u8 txr_rxr; 38 u8 dummy3[3]; 39 /* Command and Status register */ 40 u8 cr_sr; 41 u8 dummy4[3]; 42 }; 43 44 /* CTR[7:0] - Control register */ 45 46 /* I2C Core enable bit */ 47 #define M00018_CTR_BITMAP_EN_MSK (1 << 7) 48 49 /* I2C Core interrupt enable bit */ 50 #define M00018_CTR_BITMAP_IEN_MSK (1 << 6) 51 52 /* CR[7:0] - Command register */ 53 54 /* I2C start condition */ 55 #define M00018_CR_BITMAP_STA_MSK (1 << 7) 56 57 /* I2C stop condition */ 58 #define M00018_CR_BITMAP_STO_MSK (1 << 6) 59 60 /* I2C read from slave */ 61 #define M00018_CR_BITMAP_RD_MSK (1 << 5) 62 63 /* I2C write to slave */ 64 #define M00018_CR_BITMAP_WR_MSK (1 << 4) 65 66 /* I2C ack */ 67 #define M00018_CR_BITMAP_ACK_MSK (1 << 3) 68 69 /* I2C Interrupt ack */ 70 #define M00018_CR_BITMAP_IACK_MSK (1 << 0) 71 72 /* SR[7:0] - Status register */ 73 74 /* Receive acknowledge from slave */ 75 #define M00018_SR_BITMAP_RXACK_MSK (1 << 7) 76 77 /* Busy, I2C bus busy (as defined by start / stop bits) */ 78 #define M00018_SR_BITMAP_BUSY_MSK (1 << 6) 79 80 /* Arbitration lost - core lost arbitration */ 81 #define M00018_SR_BITMAP_AL_MSK (1 << 5) 82 83 /* Transfer in progress */ 84 #define M00018_SR_BITMAP_TIP_MSK (1 << 1) 85 86 /* Interrupt flag */ 87 #define M00018_SR_BITMAP_IF_MSK (1 << 0) 88 89 /* Frequency, in Hz */ 90 #define I2C_FREQUENCY 400000 91 #define ALT_CPU_FREQ 83333333 92 93 static struct cobalt_i2c_regs __iomem * 94 cobalt_i2c_regs(struct cobalt *cobalt, unsigned idx) 95 { 96 switch (idx) { 97 case 0: 98 default: 99 return (struct cobalt_i2c_regs __iomem *) 100 (cobalt->bar1 + COBALT_I2C_0_BASE); 101 case 1: 102 return (struct cobalt_i2c_regs __iomem *) 103 (cobalt->bar1 + COBALT_I2C_1_BASE); 104 case 2: 105 return (struct cobalt_i2c_regs __iomem *) 106 (cobalt->bar1 + COBALT_I2C_2_BASE); 107 case 3: 108 return (struct cobalt_i2c_regs __iomem *) 109 (cobalt->bar1 + COBALT_I2C_3_BASE); 110 case 4: 111 return (struct cobalt_i2c_regs __iomem *) 112 (cobalt->bar1 + COBALT_I2C_HSMA_BASE); 113 } 114 } 115 116 /* Do low-level i2c byte transfer. 117 * Returns -1 in case of an error or 0 otherwise. 118 */ 119 static int cobalt_tx_bytes(struct cobalt_i2c_regs __iomem *regs, 120 struct i2c_adapter *adap, bool start, bool stop, 121 u8 *data, u16 len) 122 { 123 unsigned long start_time; 124 int status; 125 int cmd; 126 int i; 127 128 for (i = 0; i < len; i++) { 129 /* Setup data */ 130 iowrite8(data[i], ®s->txr_rxr); 131 132 /* Setup command */ 133 if (i == 0 && start != 0) { 134 /* Write + Start */ 135 cmd = M00018_CR_BITMAP_WR_MSK | 136 M00018_CR_BITMAP_STA_MSK; 137 } else if (i == len - 1 && stop != 0) { 138 /* Write + Stop */ 139 cmd = M00018_CR_BITMAP_WR_MSK | 140 M00018_CR_BITMAP_STO_MSK; 141 } else { 142 /* Write only */ 143 cmd = M00018_CR_BITMAP_WR_MSK; 144 } 145 146 /* Execute command */ 147 iowrite8(cmd, ®s->cr_sr); 148 149 /* Wait for transfer to complete (TIP = 0) */ 150 start_time = jiffies; 151 status = ioread8(®s->cr_sr); 152 while (status & M00018_SR_BITMAP_TIP_MSK) { 153 if (time_after(jiffies, start_time + adap->timeout)) 154 return -ETIMEDOUT; 155 cond_resched(); 156 status = ioread8(®s->cr_sr); 157 } 158 159 /* Verify ACK */ 160 if (status & M00018_SR_BITMAP_RXACK_MSK) { 161 /* NO ACK! */ 162 return -EIO; 163 } 164 165 /* Verify arbitration */ 166 if (status & M00018_SR_BITMAP_AL_MSK) { 167 /* Arbitration lost! */ 168 return -EIO; 169 } 170 } 171 return 0; 172 } 173 174 /* Do low-level i2c byte read. 175 * Returns -1 in case of an error or 0 otherwise. 176 */ 177 static int cobalt_rx_bytes(struct cobalt_i2c_regs __iomem *regs, 178 struct i2c_adapter *adap, bool start, bool stop, 179 u8 *data, u16 len) 180 { 181 unsigned long start_time; 182 int status; 183 int cmd; 184 int i; 185 186 for (i = 0; i < len; i++) { 187 /* Setup command */ 188 if (i == 0 && start != 0) { 189 /* Read + Start */ 190 cmd = M00018_CR_BITMAP_RD_MSK | 191 M00018_CR_BITMAP_STA_MSK; 192 } else if (i == len - 1 && stop != 0) { 193 /* Read + Stop */ 194 cmd = M00018_CR_BITMAP_RD_MSK | 195 M00018_CR_BITMAP_STO_MSK; 196 } else { 197 /* Read only */ 198 cmd = M00018_CR_BITMAP_RD_MSK; 199 } 200 201 /* Last byte to read, no ACK */ 202 if (i == len - 1) 203 cmd |= M00018_CR_BITMAP_ACK_MSK; 204 205 /* Execute command */ 206 iowrite8(cmd, ®s->cr_sr); 207 208 /* Wait for transfer to complete (TIP = 0) */ 209 start_time = jiffies; 210 status = ioread8(®s->cr_sr); 211 while (status & M00018_SR_BITMAP_TIP_MSK) { 212 if (time_after(jiffies, start_time + adap->timeout)) 213 return -ETIMEDOUT; 214 cond_resched(); 215 status = ioread8(®s->cr_sr); 216 } 217 218 /* Verify arbitration */ 219 if (status & M00018_SR_BITMAP_AL_MSK) { 220 /* Arbitration lost! */ 221 return -EIO; 222 } 223 224 /* Store data */ 225 data[i] = ioread8(®s->txr_rxr); 226 } 227 return 0; 228 } 229 230 /* Generate stop condition on i2c bus. 231 * The m00018 stop isn't doing the right thing (wrong timing). 232 * So instead send a start condition, 8 zeroes and a stop condition. 233 */ 234 static int cobalt_stop(struct cobalt_i2c_regs __iomem *regs, 235 struct i2c_adapter *adap) 236 { 237 u8 data = 0; 238 239 return cobalt_tx_bytes(regs, adap, true, true, &data, 1); 240 } 241 242 static int cobalt_xfer(struct i2c_adapter *adap, 243 struct i2c_msg msgs[], int num) 244 { 245 struct cobalt_i2c_data *data = adap->algo_data; 246 struct cobalt_i2c_regs __iomem *regs = data->regs; 247 struct i2c_msg *pmsg; 248 unsigned short flags; 249 int ret = 0; 250 int i, j; 251 252 for (i = 0; i < num; i++) { 253 int stop = (i == num - 1); 254 255 pmsg = &msgs[i]; 256 flags = pmsg->flags; 257 258 if (!(pmsg->flags & I2C_M_NOSTART)) { 259 u8 addr = pmsg->addr << 1; 260 261 if (flags & I2C_M_RD) 262 addr |= 1; 263 if (flags & I2C_M_REV_DIR_ADDR) 264 addr ^= 1; 265 for (j = 0; j < adap->retries; j++) { 266 ret = cobalt_tx_bytes(regs, adap, true, false, 267 &addr, 1); 268 if (!ret) 269 break; 270 cobalt_stop(regs, adap); 271 } 272 if (ret < 0) 273 return ret; 274 ret = 0; 275 } 276 if (pmsg->flags & I2C_M_RD) { 277 /* read bytes into buffer */ 278 ret = cobalt_rx_bytes(regs, adap, false, stop, 279 pmsg->buf, pmsg->len); 280 if (ret < 0) 281 goto bailout; 282 } else { 283 /* write bytes from buffer */ 284 ret = cobalt_tx_bytes(regs, adap, false, stop, 285 pmsg->buf, pmsg->len); 286 if (ret < 0) 287 goto bailout; 288 } 289 } 290 ret = i; 291 292 bailout: 293 if (ret < 0) 294 cobalt_stop(regs, adap); 295 return ret; 296 } 297 298 static u32 cobalt_func(struct i2c_adapter *adap) 299 { 300 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 301 } 302 303 /* template for i2c-bit-algo */ 304 static struct i2c_adapter cobalt_i2c_adap_template = { 305 .name = "cobalt i2c driver", 306 .algo = NULL, /* set by i2c-algo-bit */ 307 .algo_data = NULL, /* filled from template */ 308 .owner = THIS_MODULE, 309 }; 310 311 static const struct i2c_algorithm cobalt_algo = { 312 .master_xfer = cobalt_xfer, 313 .functionality = cobalt_func, 314 }; 315 316 /* init + register i2c algo-bit adapter */ 317 int cobalt_i2c_init(struct cobalt *cobalt) 318 { 319 int i, err; 320 int status; 321 int prescale; 322 unsigned long start_time; 323 324 cobalt_dbg(1, "i2c init\n"); 325 326 /* Define I2C clock prescaler */ 327 prescale = ((ALT_CPU_FREQ) / (5 * I2C_FREQUENCY)) - 1; 328 329 for (i = 0; i < COBALT_NUM_ADAPTERS; i++) { 330 struct cobalt_i2c_regs __iomem *regs = 331 cobalt_i2c_regs(cobalt, i); 332 struct i2c_adapter *adap = &cobalt->i2c_adap[i]; 333 334 /* Disable I2C */ 335 iowrite8(M00018_CTR_BITMAP_EN_MSK, ®s->cr_sr); 336 iowrite8(0, ®s->ctr); 337 iowrite8(0, ®s->cr_sr); 338 339 start_time = jiffies; 340 do { 341 if (time_after(jiffies, start_time + HZ)) { 342 if (cobalt_ignore_err) { 343 adap->dev.parent = NULL; 344 return 0; 345 } 346 return -ETIMEDOUT; 347 } 348 status = ioread8(®s->cr_sr); 349 } while (status & M00018_SR_BITMAP_TIP_MSK); 350 351 /* Disable I2C */ 352 iowrite8(0, ®s->ctr); 353 iowrite8(0, ®s->cr_sr); 354 355 /* Calculate i2c prescaler */ 356 iowrite8(prescale & 0xff, ®s->prerlo); 357 iowrite8((prescale >> 8) & 0xff, ®s->prerhi); 358 /* Enable I2C, interrupts disabled */ 359 iowrite8(M00018_CTR_BITMAP_EN_MSK, ®s->ctr); 360 /* Setup algorithm for adapter */ 361 cobalt->i2c_data[i].cobalt = cobalt; 362 cobalt->i2c_data[i].regs = regs; 363 *adap = cobalt_i2c_adap_template; 364 adap->algo = &cobalt_algo; 365 adap->algo_data = &cobalt->i2c_data[i]; 366 adap->retries = 3; 367 sprintf(adap->name + strlen(adap->name), 368 " #%d-%d", cobalt->instance, i); 369 i2c_set_adapdata(adap, &cobalt->v4l2_dev); 370 adap->dev.parent = &cobalt->pci_dev->dev; 371 err = i2c_add_adapter(adap); 372 if (err) { 373 if (cobalt_ignore_err) { 374 adap->dev.parent = NULL; 375 return 0; 376 } 377 while (i--) 378 i2c_del_adapter(&cobalt->i2c_adap[i]); 379 return err; 380 } 381 cobalt_info("registered bus %s\n", adap->name); 382 } 383 return 0; 384 } 385 386 void cobalt_i2c_exit(struct cobalt *cobalt) 387 { 388 int i; 389 390 cobalt_dbg(1, "i2c exit\n"); 391 392 for (i = 0; i < COBALT_NUM_ADAPTERS; i++) { 393 cobalt_err("unregistered bus %s\n", cobalt->i2c_adap[i].name); 394 i2c_del_adapter(&cobalt->i2c_adap[i]); 395 } 396 } 397