1/* 2 * Nano River Technologies viperboard i2c master driver 3 * 4 * (C) 2012 by Lemonage GmbH 5 * Author: Lars Poeschel <poeschel@lemonage.de> 6 * All rights reserved. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 * 13 */ 14 15#include <linux/kernel.h> 16#include <linux/errno.h> 17#include <linux/module.h> 18#include <linux/slab.h> 19#include <linux/types.h> 20#include <linux/mutex.h> 21#include <linux/platform_device.h> 22 23#include <linux/usb.h> 24#include <linux/i2c.h> 25 26#include <linux/mfd/viperboard.h> 27 28struct vprbrd_i2c { 29 struct i2c_adapter i2c; 30 u8 bus_freq_param; 31}; 32 33/* i2c bus frequency module parameter */ 34static u8 i2c_bus_param; 35static unsigned int i2c_bus_freq = 100; 36module_param(i2c_bus_freq, int, 0); 37MODULE_PARM_DESC(i2c_bus_freq, 38 "i2c bus frequency in khz (default is 100) valid values: 10, 100, 200, 400, 1000, 3000, 6000"); 39 40static int vprbrd_i2c_status(struct i2c_adapter *i2c, 41 struct vprbrd_i2c_status *status, bool prev_error) 42{ 43 u16 bytes_xfer; 44 int ret; 45 struct vprbrd *vb = (struct vprbrd *)i2c->algo_data; 46 47 /* check for protocol error */ 48 bytes_xfer = sizeof(struct vprbrd_i2c_status); 49 50 ret = usb_control_msg(vb->usb_dev, usb_rcvctrlpipe(vb->usb_dev, 0), 51 VPRBRD_USB_REQUEST_I2C, VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, 52 status, bytes_xfer, VPRBRD_USB_TIMEOUT_MS); 53 54 if (ret != bytes_xfer) 55 prev_error = true; 56 57 if (prev_error) { 58 dev_err(&i2c->dev, "failure in usb communication\n"); 59 return -EREMOTEIO; 60 } 61 62 dev_dbg(&i2c->dev, " status = %d\n", status->status); 63 if (status->status != 0x00) { 64 dev_err(&i2c->dev, "failure: i2c protocol error\n"); 65 return -EPROTO; 66 } 67 return 0; 68} 69 70static int vprbrd_i2c_receive(struct usb_device *usb_dev, 71 struct vprbrd_i2c_read_msg *rmsg, int bytes_xfer) 72{ 73 int ret, bytes_actual; 74 int error = 0; 75 76 /* send the read request */ 77 ret = usb_bulk_msg(usb_dev, 78 usb_sndbulkpipe(usb_dev, VPRBRD_EP_OUT), rmsg, 79 sizeof(struct vprbrd_i2c_read_hdr), &bytes_actual, 80 VPRBRD_USB_TIMEOUT_MS); 81 82 if ((ret < 0) 83 || (bytes_actual != sizeof(struct vprbrd_i2c_read_hdr))) { 84 dev_err(&usb_dev->dev, "failure transmitting usb\n"); 85 error = -EREMOTEIO; 86 } 87 88 /* read the actual data */ 89 ret = usb_bulk_msg(usb_dev, 90 usb_rcvbulkpipe(usb_dev, VPRBRD_EP_IN), rmsg, 91 bytes_xfer, &bytes_actual, VPRBRD_USB_TIMEOUT_MS); 92 93 if ((ret < 0) || (bytes_xfer != bytes_actual)) { 94 dev_err(&usb_dev->dev, "failure receiving usb\n"); 95 error = -EREMOTEIO; 96 } 97 return error; 98} 99 100static int vprbrd_i2c_addr(struct usb_device *usb_dev, 101 struct vprbrd_i2c_addr_msg *amsg) 102{ 103 int ret, bytes_actual; 104 105 ret = usb_bulk_msg(usb_dev, 106 usb_sndbulkpipe(usb_dev, VPRBRD_EP_OUT), amsg, 107 sizeof(struct vprbrd_i2c_addr_msg), &bytes_actual, 108 VPRBRD_USB_TIMEOUT_MS); 109 110 if ((ret < 0) || 111 (sizeof(struct vprbrd_i2c_addr_msg) != bytes_actual)) { 112 dev_err(&usb_dev->dev, "failure transmitting usb\n"); 113 return -EREMOTEIO; 114 } 115 return 0; 116} 117 118static int vprbrd_i2c_read(struct vprbrd *vb, struct i2c_msg *msg) 119{ 120 int ret; 121 u16 remain_len, len1, len2, start = 0x0000; 122 struct vprbrd_i2c_read_msg *rmsg = 123 (struct vprbrd_i2c_read_msg *)vb->buf; 124 125 remain_len = msg->len; 126 rmsg->header.cmd = VPRBRD_I2C_CMD_READ; 127 while (remain_len > 0) { 128 rmsg->header.addr = cpu_to_le16(start + 0x4000); 129 if (remain_len <= 255) { 130 len1 = remain_len; 131 len2 = 0x00; 132 rmsg->header.len0 = remain_len; 133 rmsg->header.len1 = 0x00; 134 rmsg->header.len2 = 0x00; 135 rmsg->header.len3 = 0x00; 136 rmsg->header.len4 = 0x00; 137 rmsg->header.len5 = 0x00; 138 remain_len = 0; 139 } else if (remain_len <= 510) { 140 len1 = remain_len; 141 len2 = 0x00; 142 rmsg->header.len0 = remain_len - 255; 143 rmsg->header.len1 = 0xff; 144 rmsg->header.len2 = 0x00; 145 rmsg->header.len3 = 0x00; 146 rmsg->header.len4 = 0x00; 147 rmsg->header.len5 = 0x00; 148 remain_len = 0; 149 } else if (remain_len <= 512) { 150 len1 = remain_len; 151 len2 = 0x00; 152 rmsg->header.len0 = remain_len - 510; 153 rmsg->header.len1 = 0xff; 154 rmsg->header.len2 = 0xff; 155 rmsg->header.len3 = 0x00; 156 rmsg->header.len4 = 0x00; 157 rmsg->header.len5 = 0x00; 158 remain_len = 0; 159 } else if (remain_len <= 767) { 160 len1 = 512; 161 len2 = remain_len - 512; 162 rmsg->header.len0 = 0x02; 163 rmsg->header.len1 = 0xff; 164 rmsg->header.len2 = 0xff; 165 rmsg->header.len3 = remain_len - 512; 166 rmsg->header.len4 = 0x00; 167 rmsg->header.len5 = 0x00; 168 remain_len = 0; 169 } else if (remain_len <= 1022) { 170 len1 = 512; 171 len2 = remain_len - 512; 172 rmsg->header.len0 = 0x02; 173 rmsg->header.len1 = 0xff; 174 rmsg->header.len2 = 0xff; 175 rmsg->header.len3 = remain_len - 767; 176 rmsg->header.len4 = 0xff; 177 rmsg->header.len5 = 0x00; 178 remain_len = 0; 179 } else if (remain_len <= 1024) { 180 len1 = 512; 181 len2 = remain_len - 512; 182 rmsg->header.len0 = 0x02; 183 rmsg->header.len1 = 0xff; 184 rmsg->header.len2 = 0xff; 185 rmsg->header.len3 = remain_len - 1022; 186 rmsg->header.len4 = 0xff; 187 rmsg->header.len5 = 0xff; 188 remain_len = 0; 189 } else { 190 len1 = 512; 191 len2 = 512; 192 rmsg->header.len0 = 0x02; 193 rmsg->header.len1 = 0xff; 194 rmsg->header.len2 = 0xff; 195 rmsg->header.len3 = 0x02; 196 rmsg->header.len4 = 0xff; 197 rmsg->header.len5 = 0xff; 198 remain_len -= 1024; 199 start += 1024; 200 } 201 rmsg->header.tf1 = cpu_to_le16(len1); 202 rmsg->header.tf2 = cpu_to_le16(len2); 203 204 /* first read transfer */ 205 ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len1); 206 if (ret < 0) 207 return ret; 208 /* copy the received data */ 209 memcpy(msg->buf + start, rmsg, len1); 210 211 /* second read transfer if neccessary */ 212 if (len2 > 0) { 213 ret = vprbrd_i2c_receive(vb->usb_dev, rmsg, len2); 214 if (ret < 0) 215 return ret; 216 /* copy the received data */ 217 memcpy(msg->buf + start + 512, rmsg, len2); 218 } 219 } 220 return 0; 221} 222 223static int vprbrd_i2c_write(struct vprbrd *vb, struct i2c_msg *msg) 224{ 225 int ret, bytes_actual; 226 u16 remain_len, bytes_xfer, 227 start = 0x0000; 228 struct vprbrd_i2c_write_msg *wmsg = 229 (struct vprbrd_i2c_write_msg *)vb->buf; 230 231 remain_len = msg->len; 232 wmsg->header.cmd = VPRBRD_I2C_CMD_WRITE; 233 wmsg->header.last = 0x00; 234 wmsg->header.chan = 0x00; 235 wmsg->header.spi = 0x0000; 236 while (remain_len > 0) { 237 wmsg->header.addr = cpu_to_le16(start + 0x4000); 238 if (remain_len > 503) { 239 wmsg->header.len1 = 0xff; 240 wmsg->header.len2 = 0xf8; 241 remain_len -= 503; 242 bytes_xfer = 503 + sizeof(struct vprbrd_i2c_write_hdr); 243 start += 503; 244 } else if (remain_len > 255) { 245 wmsg->header.len1 = 0xff; 246 wmsg->header.len2 = (remain_len - 255); 247 bytes_xfer = remain_len + 248 sizeof(struct vprbrd_i2c_write_hdr); 249 remain_len = 0; 250 } else { 251 wmsg->header.len1 = remain_len; 252 wmsg->header.len2 = 0x00; 253 bytes_xfer = remain_len + 254 sizeof(struct vprbrd_i2c_write_hdr); 255 remain_len = 0; 256 } 257 memcpy(wmsg->data, msg->buf + start, 258 bytes_xfer - sizeof(struct vprbrd_i2c_write_hdr)); 259 260 ret = usb_bulk_msg(vb->usb_dev, 261 usb_sndbulkpipe(vb->usb_dev, 262 VPRBRD_EP_OUT), wmsg, 263 bytes_xfer, &bytes_actual, VPRBRD_USB_TIMEOUT_MS); 264 if ((ret < 0) || (bytes_xfer != bytes_actual)) 265 return -EREMOTEIO; 266 } 267 return 0; 268} 269 270static int vprbrd_i2c_xfer(struct i2c_adapter *i2c, struct i2c_msg *msgs, 271 int num) 272{ 273 struct i2c_msg *pmsg; 274 int i, ret, 275 error = 0; 276 struct vprbrd *vb = (struct vprbrd *)i2c->algo_data; 277 struct vprbrd_i2c_addr_msg *amsg = 278 (struct vprbrd_i2c_addr_msg *)vb->buf; 279 struct vprbrd_i2c_status *smsg = (struct vprbrd_i2c_status *)vb->buf; 280 281 dev_dbg(&i2c->dev, "master xfer %d messages:\n", num); 282 283 for (i = 0 ; i < num ; i++) { 284 pmsg = &msgs[i]; 285 286 dev_dbg(&i2c->dev, 287 " %d: %s (flags %d) %d bytes to 0x%02x\n", 288 i, pmsg->flags & I2C_M_RD ? "read" : "write", 289 pmsg->flags, pmsg->len, pmsg->addr); 290 291 mutex_lock(&vb->lock); 292 /* directly send the message */ 293 if (pmsg->flags & I2C_M_RD) { 294 /* read data */ 295 amsg->cmd = VPRBRD_I2C_CMD_ADDR; 296 amsg->unknown2 = 0x00; 297 amsg->unknown3 = 0x00; 298 amsg->addr = pmsg->addr; 299 amsg->unknown1 = 0x01; 300 amsg->len = cpu_to_le16(pmsg->len); 301 /* send the addr and len, we're interested to board */ 302 ret = vprbrd_i2c_addr(vb->usb_dev, amsg); 303 if (ret < 0) 304 error = ret; 305 306 ret = vprbrd_i2c_read(vb, pmsg); 307 if (ret < 0) 308 error = ret; 309 310 ret = vprbrd_i2c_status(i2c, smsg, error); 311 if (ret < 0) 312 error = ret; 313 /* in case of protocol error, return the error */ 314 if (error < 0) 315 goto error; 316 } else { 317 /* write data */ 318 ret = vprbrd_i2c_write(vb, pmsg); 319 320 amsg->cmd = VPRBRD_I2C_CMD_ADDR; 321 amsg->unknown2 = 0x00; 322 amsg->unknown3 = 0x00; 323 amsg->addr = pmsg->addr; 324 amsg->unknown1 = 0x00; 325 amsg->len = cpu_to_le16(pmsg->len); 326 /* send the addr, the data goes to to board */ 327 ret = vprbrd_i2c_addr(vb->usb_dev, amsg); 328 if (ret < 0) 329 error = ret; 330 331 ret = vprbrd_i2c_status(i2c, smsg, error); 332 if (ret < 0) 333 error = ret; 334 335 if (error < 0) 336 goto error; 337 } 338 mutex_unlock(&vb->lock); 339 } 340 return 0; 341error: 342 mutex_unlock(&vb->lock); 343 return error; 344} 345 346static u32 vprbrd_i2c_func(struct i2c_adapter *i2c) 347{ 348 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; 349} 350 351/* This is the actual algorithm we define */ 352static const struct i2c_algorithm vprbrd_algorithm = { 353 .master_xfer = vprbrd_i2c_xfer, 354 .functionality = vprbrd_i2c_func, 355}; 356 357static struct i2c_adapter_quirks vprbrd_quirks = { 358 .max_read_len = 2048, 359 .max_write_len = 2048, 360}; 361 362static int vprbrd_i2c_probe(struct platform_device *pdev) 363{ 364 struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent); 365 struct vprbrd_i2c *vb_i2c; 366 int ret; 367 int pipe; 368 369 vb_i2c = devm_kzalloc(&pdev->dev, sizeof(*vb_i2c), GFP_KERNEL); 370 if (vb_i2c == NULL) 371 return -ENOMEM; 372 373 /* setup i2c adapter description */ 374 vb_i2c->i2c.owner = THIS_MODULE; 375 vb_i2c->i2c.class = I2C_CLASS_HWMON; 376 vb_i2c->i2c.algo = &vprbrd_algorithm; 377 vb_i2c->i2c.quirks = &vprbrd_quirks; 378 vb_i2c->i2c.algo_data = vb; 379 /* save the param in usb capabable memory */ 380 vb_i2c->bus_freq_param = i2c_bus_param; 381 382 snprintf(vb_i2c->i2c.name, sizeof(vb_i2c->i2c.name), 383 "viperboard at bus %03d device %03d", 384 vb->usb_dev->bus->busnum, vb->usb_dev->devnum); 385 386 /* setting the bus frequency */ 387 if ((i2c_bus_param <= VPRBRD_I2C_FREQ_10KHZ) 388 && (i2c_bus_param >= VPRBRD_I2C_FREQ_6MHZ)) { 389 pipe = usb_sndctrlpipe(vb->usb_dev, 0); 390 ret = usb_control_msg(vb->usb_dev, pipe, 391 VPRBRD_USB_REQUEST_I2C_FREQ, VPRBRD_USB_TYPE_OUT, 392 0x0000, 0x0000, &vb_i2c->bus_freq_param, 1, 393 VPRBRD_USB_TIMEOUT_MS); 394 if (ret != 1) { 395 dev_err(&pdev->dev, "failure setting i2c_bus_freq to %d\n", 396 i2c_bus_freq); 397 return -EIO; 398 } 399 } else { 400 dev_err(&pdev->dev, 401 "invalid i2c_bus_freq setting:%d\n", i2c_bus_freq); 402 return -EIO; 403 } 404 405 vb_i2c->i2c.dev.parent = &pdev->dev; 406 407 /* attach to i2c layer */ 408 i2c_add_adapter(&vb_i2c->i2c); 409 410 platform_set_drvdata(pdev, vb_i2c); 411 412 return 0; 413} 414 415static int vprbrd_i2c_remove(struct platform_device *pdev) 416{ 417 struct vprbrd_i2c *vb_i2c = platform_get_drvdata(pdev); 418 419 i2c_del_adapter(&vb_i2c->i2c); 420 421 return 0; 422} 423 424static struct platform_driver vprbrd_i2c_driver = { 425 .driver.name = "viperboard-i2c", 426 .driver.owner = THIS_MODULE, 427 .probe = vprbrd_i2c_probe, 428 .remove = vprbrd_i2c_remove, 429}; 430 431static int __init vprbrd_i2c_init(void) 432{ 433 switch (i2c_bus_freq) { 434 case 6000: 435 i2c_bus_param = VPRBRD_I2C_FREQ_6MHZ; 436 break; 437 case 3000: 438 i2c_bus_param = VPRBRD_I2C_FREQ_3MHZ; 439 break; 440 case 1000: 441 i2c_bus_param = VPRBRD_I2C_FREQ_1MHZ; 442 break; 443 case 400: 444 i2c_bus_param = VPRBRD_I2C_FREQ_400KHZ; 445 break; 446 case 200: 447 i2c_bus_param = VPRBRD_I2C_FREQ_200KHZ; 448 break; 449 case 100: 450 i2c_bus_param = VPRBRD_I2C_FREQ_100KHZ; 451 break; 452 case 10: 453 i2c_bus_param = VPRBRD_I2C_FREQ_10KHZ; 454 break; 455 default: 456 pr_warn("invalid i2c_bus_freq (%d)\n", i2c_bus_freq); 457 i2c_bus_param = VPRBRD_I2C_FREQ_100KHZ; 458 } 459 460 return platform_driver_register(&vprbrd_i2c_driver); 461} 462subsys_initcall(vprbrd_i2c_init); 463 464static void __exit vprbrd_i2c_exit(void) 465{ 466 platform_driver_unregister(&vprbrd_i2c_driver); 467} 468module_exit(vprbrd_i2c_exit); 469 470MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>"); 471MODULE_DESCRIPTION("I2C master driver for Nano River Techs Viperboard"); 472MODULE_LICENSE("GPL"); 473MODULE_ALIAS("platform:viperboard-i2c"); 474