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