├── Kbuild ├── .gitignore ├── README.md ├── create_pdata.c └── spi-cp2130.c /Kbuild: -------------------------------------------------------------------------------- 1 | obj-m := spi-cp2130.o 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .built* 2 | .spi* 3 | built* 4 | .tmp* 5 | Module* 6 | modules* 7 | *~ 8 | *.o 9 | *.ko 10 | *.mod.* 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Linux kernel driver for Silicon Labs CP2130 USB-SPI Bridge 2 | 3 | * datasheet: https://www.silabs.com/Support%20Documents/TechnicalDocs/CP2130.pdf 4 | 5 | * for out-of-tree build please refer to https://www.kernel.org/doc/Documentation/kbuild/modules.txt 6 | 7 | * sysfs API 8 | * irq_poll_interval: specifies the IRQ/GPIO poll interval in us. 9 | * channel_pdata: binary load of platform data for SPI driver. The create_pdata.c 10 | program gives an example how to create binary platform data 11 | for the mcp251x. 12 | * channel_config: attach SPI driver to certain channel, e. g. to 13 | plug the mcp251x CAN driver use 14 | `echo -n 0,2,6,0,0,0,1,0,0,0,0,mcp2515 > /sys/.../channel_config` 15 | or 16 | `echo -n 0,2,-1,1,1,1,0,0,0,0,0,spidev > /sys/.../channel_config` and 17 | `echo -n 1,2,-1,1,1,1,0,0,0,0,0,spidev > /sys/.../channel_config` 18 | ` for 2 general purpose spidev without IRQ support. 19 | For the values to be entered in the columns please 20 | refer to the CP2130 datasheet. 21 | * otp_rom: you can read the current OTP ROM settings and their lock 22 | status or write a new OTP ROM configuration, please make 23 | sure that you do the right thing, OTP means one-time-programmable! 24 | 25 | * GPIO chip: the driver implements a GPIO chip for all GPIOs of the CP2130, 26 | they can be accessed from userspace using the sysfs GPIO API 27 | or directly from another driver. 28 | -------------------------------------------------------------------------------- /create_pdata.c: -------------------------------------------------------------------------------- 1 | /* gcc -o create_pdata create_pdata.c */ 2 | /* supported devices: 3 | * mcp2515 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | struct mcp251x_platform_data { 16 | unsigned long oscillator_frequency; 17 | }; 18 | 19 | int main(int argc, char *argv[]) { 20 | void *pdata; 21 | char fname[256] = { 0 }; 22 | int fd; 23 | uint8_t chn = 0; 24 | int ret; 25 | 26 | if (argc < 3) { 27 | printf("usage - %s \n", 28 | argv[0]); 29 | return -EINVAL; 30 | } 31 | 32 | strcpy(fname, argv[1]); 33 | strcat(fname, ".pdata"); 34 | fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 35 | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); 36 | if (fd < 0) { 37 | printf("failed to open file %s\n", fname); 38 | return -EINVAL; 39 | } 40 | 41 | pdata = calloc(1, sizeof(struct mcp251x_platform_data)); 42 | if (!pdata) { 43 | printf("failed to allocate memory for pdata\n"); 44 | ret = -ENOMEM; 45 | goto out_file; 46 | } 47 | 48 | if (!strcmp(argv[1], "mcp2515")) { 49 | ((struct mcp251x_platform_data*) pdata)-> 50 | oscillator_frequency = strtoul(argv[2], NULL, 0); 51 | ret = write(fd, &chn, sizeof(uint8_t)); 52 | if (ret < sizeof(uint8_t)) { 53 | printf("failed to wite file %s\n", fname); 54 | ret = -EIO; 55 | goto out_mem; 56 | } 57 | ret = write(fd, pdata, sizeof(struct mcp251x_platform_data)); 58 | if (ret < sizeof(struct mcp251x_platform_data)) { 59 | printf("failed to wite file %s\n", fname); 60 | ret = -EIO; 61 | goto out_mem; 62 | } 63 | } 64 | 65 | out_mem: 66 | free(pdata); 67 | 68 | out_file: 69 | close(fd); 70 | 71 | return ret; 72 | } 73 | -------------------------------------------------------------------------------- /spi-cp2130.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Kernel driver for CP2130 USB<->SPI bridge. 3 | * Copyright (C) 2016 Jochen Henneberg (jh@henneberg-systemdesign.com) 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public License 7 | * as published by the Free Software Foundation; either version 2 8 | * of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with this program; if not, write to the Free Software 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define USB_DEVICE_ID_CP2130 0x87a0 34 | #define USB_VENDOR_ID_CYGNAL 0x10c4 35 | 36 | #define CP2130_NUM_GPIOS 11 37 | #define CP2130_IRQ_POLL_INTERVAL 1 * 1000 * 1000 /* us */ 38 | 39 | #define CP2130_MAX_USB_PACKET_SIZE 64 40 | 41 | #define CP2130_CMD_READ 0x00 42 | #define CP2130_CMD_WRITE 0x01 43 | #define CP2130_CMD_WRITEREAD 0x02 44 | #define CP2130_BULK_OFFSET_CMD 2 45 | #define CP2130_BULK_OFFSET_LENGTH 4 46 | #define CP2130_BULK_OFFSET_DATA 8 47 | #define CP2130_BULK_HEADER_SIZE (CP2130_BULK_OFFSET_DATA) 48 | 49 | #define CP2130_BREQ_GET_GPIO_VALUES 0x20 50 | #define CP2130_BREQ_SET_GPIO_MODE 0x23 51 | #define CP2130_BREQ_GET_GPIO_CS 0x24 52 | #define CP2130_BREQ_SET_GPIO_CS 0x25 53 | #define CP2130_BREQ_GET_SPI_WORD 0x30 54 | #define CP2130_BREQ_SET_SPI_WORD 0x31 55 | #define CP2130_BREQ_GET_SPI_DELAY 0x32 56 | #define CP2130_BREQ_SET_SPI_DELAY 0x33 57 | #define CP2130_BREQ_GET_LOCK_BYTE 0x6E 58 | #define CP2130_BREQ_GET_PIN_CONFIG 0x6C 59 | #define CP2130_BREQ_SET_PIN_CONFIG 0x6D 60 | 61 | #define CP2130_BREQ_MEMORY_KEY 0xA5F1 62 | 63 | /* cp2130 attached chip */ 64 | struct cp2130_channel { 65 | int updated; 66 | int cs_en; /* chip-select enable mode */ 67 | int irq_pin; 68 | int clock_phase; 69 | int polarity; 70 | int cs_pin_mode; 71 | int clock_freq; /* spi clock frequency */ 72 | int delay_mask; /* cs enable, pre-deassert, 73 | post assert and inter-byte delay enable */ 74 | int inter_byte_delay; 75 | int pre_deassert_delay; 76 | int post_assert_delay; 77 | char *modalias; 78 | void *pdata; 79 | struct spi_device *chip; 80 | }; 81 | 82 | /* cp2130 OTP ROM */ 83 | struct cp2130_otprom { 84 | int lock_byte; 85 | int pin_config[CP2130_NUM_GPIOS]; 86 | int suspend_level; 87 | int suspend_mode; 88 | int wakeup_mask; 89 | int wakeup_match; 90 | int divider; 91 | }; 92 | 93 | struct cp2130_gpio_irq { 94 | struct irq_domain *irq_domain; 95 | struct mutex irq_lock; 96 | int virq[CP2130_NUM_GPIOS]; 97 | u16 irq_mask; 98 | }; 99 | 100 | /* cp2130 device structure */ 101 | struct cp2130_device { 102 | struct usb_device *udev; 103 | struct usb_interface *intf; 104 | struct spi_master *spi_master; 105 | 106 | struct mutex chn_config_lock; 107 | struct mutex otprom_lock; 108 | struct mutex usb_bus_lock; 109 | 110 | struct work_struct update_chn_config; 111 | struct work_struct read_chn_config; 112 | struct work_struct update_otprom; 113 | struct work_struct read_otprom; 114 | struct cp2130_channel chn_configs[CP2130_NUM_GPIOS]; 115 | struct cp2130_otprom otprom_config; 116 | 117 | struct cp2130_gpio_irq irq_chip; 118 | struct work_struct irq_work; 119 | 120 | struct gpio_chip gpio_chip; 121 | char *gpio_names[CP2130_NUM_GPIOS]; 122 | u8 gpio_states[2]; 123 | 124 | int current_channel; 125 | 126 | int irq_poll_interval; 127 | 128 | u8 *usb_xfer; 129 | }; 130 | 131 | /* Prototypes */ 132 | static int cp2130_probe(struct usb_interface *intf, 133 | const struct usb_device_id *id); 134 | static void cp2130_disconnect(struct usb_interface *intf); 135 | 136 | static const struct usb_device_id cp2130_devices[] = { 137 | { USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CP2130) }, 138 | { } 139 | }; 140 | 141 | /* USB device functions */ 142 | static struct usb_driver cp2130_driver = { 143 | .name = "cp2130", 144 | .probe = cp2130_probe, 145 | .disconnect = cp2130_disconnect, 146 | .suspend = NULL, 147 | .resume = NULL, 148 | .reset_resume = NULL, 149 | .id_table = cp2130_devices, 150 | .supports_autosuspend = 0, 151 | }; 152 | 153 | static int __init cp2130_init(void) 154 | { 155 | int ret; 156 | printk(KERN_DEBUG "cp2130_init\n"); 157 | ret = usb_register_driver(&cp2130_driver, THIS_MODULE, "cp2130"); 158 | if (ret) 159 | printk(KERN_ERR "can't register cp2130 driver\n"); 160 | 161 | return ret; 162 | } 163 | 164 | static void __exit cp2130_exit(void) 165 | { 166 | printk(KERN_DEBUG "cp2130_exit\n"); 167 | usb_deregister(&cp2130_driver); 168 | } 169 | 170 | static int cp2130_spi_setup(struct spi_device *spi) 171 | { 172 | return 0; 173 | } 174 | 175 | static void cp2130_spi_cleanup(struct spi_device *spi) 176 | { 177 | } 178 | 179 | static char* cp2130_spi_speed_to_string(int reg_val) 180 | { 181 | switch (reg_val) { 182 | case 0: return "12 MHz "; 183 | case 1: return "6 MHz "; 184 | case 2: return "3 MHz "; 185 | case 3: return "1.5 MHz "; 186 | case 4: return "750 kHz "; 187 | case 5: return "375 kHz "; 188 | case 6: return "187.5 kHz"; 189 | case 7: return "93.8 kHz "; 190 | } 191 | return ""; 192 | } 193 | 194 | static unsigned int cp2130_spi_speed_to_nsec(int reg_val) 195 | { 196 | #define USEC (1 * 1000 * 1000) 197 | #define FREQ_MHZ(n) (n * 1000) 198 | #define FREQ_KHZ(n) (n) 199 | 200 | switch (reg_val) { 201 | case 0: return (USEC / FREQ_MHZ(12)); 202 | case 1: return (USEC / FREQ_MHZ(6)); 203 | case 2: return (USEC / FREQ_MHZ(3)); 204 | case 3: return (USEC / FREQ_KHZ(1500)); 205 | case 4: return (USEC / FREQ_KHZ(750)); 206 | case 5: return (USEC / FREQ_KHZ(375)); 207 | case 6: return (USEC / FREQ_KHZ(187)); 208 | case 7: return (USEC / FREQ_KHZ(93)); 209 | } 210 | return (USEC / FREQ_KHZ(93)); 211 | } 212 | 213 | /* 214 | * This is a workaround for older versions of linux which do not have 215 | * gpiochip_add(). In this module, the data parameter passed to 216 | * gpiochip_add_data is always the struct cp2130_device that contains the struct 217 | * gpio_chip that is passed as the first parameter. Based on this assumption we 218 | * can simulate the correct behaviour using container_of() to get the struct 219 | * cp2130_device from the struct gpio_chip. 220 | */ 221 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 4, 0) 222 | static inline struct cp2130_device *gpiochip_get_data(struct gpio_chip *chip) 223 | { 224 | return container_of(chip, struct cp2130_device, gpio_chip); 225 | } 226 | 227 | static inline int gpiochip_add_data(struct gpio_chip *chip, void *data) 228 | { 229 | return gpiochip_add(chip); 230 | } 231 | #endif 232 | 233 | /* 234 | * This is a workaround for older versions of linux which have a __must_check 235 | * return type of int on the gpiochip_remove() function. 236 | */ 237 | static inline void gpiochip_remove_(struct gpio_chip *chip) 238 | { 239 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) 240 | if (gpiochip_remove(chip) < 0) 241 | dev_err(&gpiochip_get_data(chip)->intf->dev, 242 | "failed to remove GPIO chip"); 243 | #else 244 | gpiochip_remove(chip); 245 | #endif 246 | } 247 | 248 | static ssize_t channel_config_show(struct device *dev, 249 | struct device_attribute *attr, char *buf) 250 | { 251 | struct usb_interface *intf; 252 | struct usb_device *udev; 253 | struct cp2130_device *chip; 254 | struct cp2130_channel *chn; 255 | int i = 0; 256 | char out[256]; 257 | ssize_t ret; 258 | 259 | intf = to_usb_interface(dev); 260 | if (!intf) 261 | return -EFAULT; 262 | 263 | chip = usb_get_intfdata(intf); 264 | if (!chip) 265 | return -EFAULT; 266 | 267 | udev = usb_get_dev(interface_to_usbdev(intf)); 268 | if (!udev) 269 | return -EFAULT; 270 | 271 | ret = sprintf(out, "channel\tcs_mode\tirq_pin\tclock_phase\tpolarity" 272 | "\tcs_pin_mode\tclock_freq\tdelay_mask" 273 | "\tinter_byte_delay\tpre_delay\tpost_delay" 274 | "\tmod_alias\n"); 275 | strcat(buf, out); 276 | mutex_lock(&chip->chn_config_lock); 277 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 278 | chn = &chip->chn_configs[i]; 279 | ret += sprintf(out, "%d\t%d\t%d\t%d\t\t%d\t\t%d\t\t%s\t%d" 280 | "\t\t%d\t\t\t%d\t\t%d\t\t'%s'\n", 281 | i, chn->cs_en, chn->irq_pin, chn->clock_phase, 282 | chn->polarity, chn->cs_pin_mode, 283 | cp2130_spi_speed_to_string(chn->clock_freq), 284 | chn->delay_mask, chn->inter_byte_delay, 285 | chn->pre_deassert_delay, chn->post_assert_delay, 286 | chn->modalias); 287 | strcat(buf, out); 288 | } 289 | mutex_unlock(&chip->chn_config_lock); 290 | 291 | return ret; 292 | } 293 | 294 | static ssize_t channel_config_store(struct device *dev, 295 | struct device_attribute *attr, 296 | const char *buf, size_t count) 297 | { 298 | struct cp2130_channel chn; 299 | struct usb_interface *intf; 300 | struct usb_device *udev; 301 | struct cp2130_device *chip; 302 | char *lbuf; 303 | char *del; /* delimiter ',' */ 304 | char *pos; /* current item position in buffer */ 305 | int i, ret, eos, chn_id; 306 | 307 | intf = to_usb_interface(dev); 308 | if (!intf) 309 | return -EFAULT; 310 | 311 | chip = usb_get_intfdata(intf); 312 | if (!chip) 313 | return -EFAULT; 314 | 315 | udev = usb_get_dev(interface_to_usbdev(intf)); 316 | if (!udev) 317 | return -EFAULT; 318 | 319 | dev_dbg(&udev->dev, "received '%s' from 'channel_config'", buf); 320 | 321 | if (!count) 322 | return -EINVAL; 323 | 324 | lbuf = kstrdup(buf, GFP_KERNEL); 325 | if (!lbuf) 326 | return -ENOMEM; 327 | 328 | pos = lbuf; 329 | eos = i = 0; 330 | do { 331 | /* search for next separator or end-of-string */ 332 | del = strchr(pos, ','); 333 | if (!del) 334 | del = strchr(pos, '\0'); 335 | if (!del) { 336 | ret = -EINVAL; 337 | goto out; 338 | } 339 | 340 | if (*del == '\0') 341 | eos = 1; 342 | *del = '\0'; 343 | 344 | dev_dbg(&udev->dev, "parsing: %s(%d)", pos, i); 345 | 346 | /* parse current item */ 347 | switch (i) { 348 | case 0: /* channel id */ 349 | ret = kstrtoint(pos, 10, &chn_id); 350 | ret |= (chn_id < 0 || chn_id > 10) ? -EINVAL : 0; 351 | if (ret) 352 | goto out; 353 | break; 354 | case 1: /* chip-select enable */ 355 | ret = kstrtoint(pos, 10, &chn.cs_en); 356 | ret |= (chn.cs_en < 0 || chn.cs_en > 2) ? -EINVAL : 0; 357 | if (ret) 358 | goto out; 359 | break; 360 | case 2: /* irq pin */ 361 | ret = kstrtoint(pos, 10, &chn.irq_pin); 362 | ret |= (chn.irq_pin > 10) ? -EINVAL : 0; 363 | if (ret) 364 | goto out; 365 | break; 366 | case 3: /* clock phase */ 367 | ret = kstrtoint(pos, 10, &chn.clock_phase); 368 | if (ret) 369 | goto out; 370 | chn.clock_phase = !!chn.clock_phase; 371 | break; 372 | case 4: /* polarity */ 373 | ret = kstrtoint(pos, 10, &chn.polarity); 374 | if (ret) 375 | goto out; 376 | chn.polarity = !!chn.polarity; 377 | break; 378 | case 5: /* chip-select pin mode */ 379 | ret = kstrtoint(pos, 10, &chn.cs_pin_mode); 380 | if (ret) 381 | goto out; 382 | chn.cs_pin_mode = !!chn.cs_pin_mode; 383 | break; 384 | case 6: /* spi clock frequency */ 385 | ret = kstrtoint(pos, 10, &chn.clock_freq); 386 | ret |= (chn.clock_freq < 0 || chn.clock_freq > 7) ? 387 | -EINVAL : 0; 388 | if (ret) 389 | goto out; 390 | break; 391 | case 7: /* delay mask */ 392 | ret = kstrtoint(pos, 10, &chn.delay_mask); 393 | ret |= (chn.delay_mask < 0 || chn.delay_mask > 15) ? 394 | -EINVAL : 0; 395 | if (ret) 396 | goto out; 397 | break; 398 | case 8: /* inter-byte delay */ 399 | ret = kstrtoint(pos, 10, &chn.inter_byte_delay); 400 | ret |= (chn.inter_byte_delay < 0 || 401 | chn.inter_byte_delay > 0xffff) ? 402 | -EINVAL : 0; 403 | if (ret) 404 | goto out; 405 | break; 406 | case 9: /* pre-deassert delay */ 407 | ret = kstrtoint(pos, 10, &chn.pre_deassert_delay); 408 | ret |= (chn.pre_deassert_delay < 0 || 409 | chn.pre_deassert_delay > 0xffff) ? 410 | -EINVAL : 0; 411 | if (ret) 412 | goto out; 413 | break; 414 | case 10: /* post-assert delay */ 415 | ret = kstrtoint(pos, 10, &chn.post_assert_delay); 416 | ret |= (chn.post_assert_delay < 0 || 417 | chn.post_assert_delay > 0xffff) ? 418 | -EINVAL : 0; 419 | if (ret) 420 | goto out; 421 | break; 422 | case 11: /* modalias */ 423 | chn.modalias = kstrdup(pos, GFP_KERNEL); 424 | if (!chn.modalias) { 425 | ret = -EINVAL; 426 | goto out; 427 | } 428 | break; 429 | default: 430 | ret = -EINVAL; 431 | goto out; 432 | } 433 | 434 | /* move the parser position forward */ 435 | pos = ++del; 436 | i++; 437 | } while (!eos); 438 | 439 | if (i < 11) { 440 | ret = -EINVAL; 441 | goto out; 442 | } 443 | 444 | chn.updated = 1; 445 | mutex_lock(&chip->chn_config_lock); 446 | if (chip->chn_configs[chn_id].updated) { 447 | ret = -EINVAL; 448 | goto unlock; 449 | } 450 | /* preserve pdata */ 451 | chn.pdata = chip->chn_configs[chn_id].pdata; 452 | 453 | memcpy(&chip->chn_configs[chn_id], &chn, sizeof(chn)); 454 | schedule_work(&chip->update_chn_config); 455 | ret = count; 456 | 457 | unlock: 458 | mutex_unlock(&chip->chn_config_lock); 459 | 460 | out: 461 | kfree(lbuf); 462 | return ret; 463 | } 464 | static DEVICE_ATTR_RW(channel_config); 465 | 466 | 467 | static ssize_t channel_pdata_store(struct device *dev, 468 | struct device_attribute *attr, 469 | const char *buf, size_t count) 470 | { 471 | struct usb_interface *intf; 472 | struct usb_device *udev; 473 | struct cp2130_device *chip; 474 | struct cp2130_channel *chn; 475 | int chn_id; 476 | int ret; 477 | 478 | intf = to_usb_interface(dev); 479 | if (!intf) 480 | return -EFAULT; 481 | 482 | chip = usb_get_intfdata(intf); 483 | if (!chip) 484 | return -EFAULT; 485 | 486 | udev = usb_get_dev(interface_to_usbdev(intf)); 487 | if (!udev) 488 | return -EFAULT; 489 | 490 | /* first byte is channel id, 491 | then follows binary platform data */ 492 | if (count < 2) 493 | return -EINVAL; 494 | 495 | chn_id = buf[0]; 496 | dev_dbg(&udev->dev, "received pdata for channel %u", chn_id); 497 | 498 | if (chn_id < 0 || chn_id >= CP2130_NUM_GPIOS) 499 | return -EINVAL; 500 | 501 | chn = &chip->chn_configs[chn_id]; 502 | 503 | /* pdata can be set only once */ 504 | if (chn->pdata) { 505 | ret = -EINVAL; 506 | goto out; 507 | } 508 | 509 | dev_dbg(&udev->dev, "set pdata for channel %u", chn_id); 510 | 511 | mutex_lock(&chip->chn_config_lock); 512 | chn->pdata = kzalloc(count - 1, GFP_KERNEL); 513 | if (!chn->pdata) { 514 | ret = -ENOMEM; 515 | goto out; 516 | } 517 | 518 | if (!memcpy(chn->pdata, buf + 1, count - 1)) { 519 | kfree(chn->pdata); 520 | chn->pdata = NULL; 521 | ret = -EIO; 522 | goto out; 523 | } 524 | 525 | ret = count; 526 | out: 527 | mutex_unlock(&chip->chn_config_lock); 528 | return ret; 529 | } 530 | static DEVICE_ATTR_WO(channel_pdata); 531 | 532 | static char* cp2130_pin_mode_to_string(int val) 533 | { 534 | switch (val) { 535 | case 0: return "in "; 536 | case 1: return "open-drain"; 537 | case 2: return "push-pull "; 538 | case 3: return "nCS "; 539 | default: return "special "; 540 | } 541 | return ""; 542 | } 543 | 544 | static ssize_t otp_rom_show(struct device *dev, 545 | struct device_attribute *attr, char *buf) 546 | { 547 | struct usb_interface *intf; 548 | struct usb_device *udev; 549 | struct cp2130_device *chip; 550 | int pin; 551 | int i = 0; 552 | char out[256]; 553 | ssize_t ret; 554 | 555 | intf = to_usb_interface(dev); 556 | if (!intf) 557 | return -EFAULT; 558 | 559 | chip = usb_get_intfdata(intf); 560 | if (!chip) 561 | return -EFAULT; 562 | 563 | udev = usb_get_dev(interface_to_usbdev(intf)); 564 | if (!udev) 565 | return -EFAULT; 566 | 567 | mutex_lock(&chip->otprom_lock); 568 | 569 | ret = sprintf(out, "OTP lock status (ro):" 570 | "\nvid\t\tpid\t\tmax_power\tpower_mode" 571 | "\tversion\t\tmanu_2\t\tmanu_1" 572 | "\t\tpriority\tproduct_1\tproduct_2\tserial" 573 | "\t\tpin_config\n"); 574 | strcat(buf, out); 575 | for (i = 0; i < 12; i++) { 576 | if (!!((chip->otprom_config.lock_byte >> i) & 1)) 577 | ret += sprintf(out, "unlocked\t"); 578 | else 579 | ret += sprintf(out, "locked\t\t"); 580 | strcat(buf, out); 581 | } 582 | ret += sprintf(out, "\n\nOTP pin configuration (rw):\n"); 583 | strcat(buf, out); 584 | 585 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 586 | ret += sprintf(out, "pin %d\t\t", i); 587 | strcat(buf, out); 588 | } 589 | strcat(buf, "\n"); 590 | ret++; 591 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 592 | pin = chip->otprom_config.pin_config[i]; 593 | ret += sprintf(out, "%s\t", cp2130_pin_mode_to_string(pin)); 594 | strcat(buf, out); 595 | } 596 | 597 | ret += sprintf(out, "\n\nOTP pin configuration extra data(ro):" 598 | "\nsuspend_level\tsuspend_mode\twakeup_mask\twakeup_match" 599 | "\tdivider\n"); 600 | strcat(buf, out); 601 | ret += sprintf(out, "%d\t\t%d\t\t%d\t\t%d\t\t%d\n", 602 | chip->otprom_config.suspend_level, 603 | chip->otprom_config.suspend_mode, 604 | chip->otprom_config.wakeup_mask, 605 | chip->otprom_config.wakeup_match, 606 | chip->otprom_config.divider); 607 | strcat(buf, out); 608 | 609 | mutex_unlock(&chip->otprom_lock); 610 | 611 | return ret; 612 | } 613 | 614 | static ssize_t otp_rom_store(struct device *dev, 615 | struct device_attribute *attr, 616 | const char *buf, size_t count) 617 | { 618 | int pin_config[CP2130_NUM_GPIOS]; 619 | struct usb_interface *intf; 620 | struct usb_device *udev; 621 | struct cp2130_device *chip; 622 | char *lbuf; 623 | char *del; /* delimiter ',' */ 624 | char *pos; /* current item position in buffer */ 625 | int i, ret, eos; 626 | 627 | intf = to_usb_interface(dev); 628 | if (!intf) 629 | return -EFAULT; 630 | 631 | chip = usb_get_intfdata(intf); 632 | if (!chip) 633 | return -EFAULT; 634 | 635 | udev = usb_get_dev(interface_to_usbdev(intf)); 636 | if (!udev) 637 | return -EFAULT; 638 | 639 | dev_dbg(&udev->dev, "received '%s' from 'otp_rom'", buf); 640 | 641 | if (!count) 642 | return -EINVAL; 643 | 644 | lbuf = kstrdup(buf, GFP_KERNEL); 645 | if (!lbuf) 646 | return -ENOMEM; 647 | 648 | pos = lbuf; 649 | eos = i = 0; 650 | do { 651 | /* search for next separator or end-of-string */ 652 | del = strchr(pos, ','); 653 | if (!del) 654 | del = strchr(pos, '\0'); 655 | if (!del) { 656 | ret = -EINVAL; 657 | goto out; 658 | } 659 | 660 | if (*del == '\0') 661 | eos = 1; 662 | *del = '\0'; 663 | 664 | dev_dbg(&udev->dev, "parsing: %s(%d)", pos, i); 665 | 666 | if (i == CP2130_NUM_GPIOS) { 667 | ret = -EINVAL; 668 | goto out; 669 | } 670 | 671 | /* parse current item */ 672 | if (*pos == 'x') { 673 | pin_config[i] = -1; 674 | } else { 675 | ret = kstrtoint(pos, 10, &(pin_config[i])); 676 | ret |= (pin_config[i] < 0 || 677 | pin_config[i] > 3) ? 678 | -EINVAL : 0; 679 | if (ret) 680 | goto out; 681 | } 682 | 683 | /* move the parser position forward */ 684 | pos = ++del; 685 | i++; 686 | } while (!eos); 687 | 688 | if (i < 11) { 689 | ret = -EINVAL; 690 | goto out; 691 | } 692 | 693 | mutex_lock(&chip->otprom_lock); 694 | 695 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 696 | if (pin_config[i] < 0) 697 | continue; 698 | printk(KERN_INFO "cp2130 read OTP: %d", pin_config[i]); 699 | chip->otprom_config.pin_config[i] = pin_config[i]; 700 | } 701 | schedule_work(&chip->update_otprom); 702 | ret = count; 703 | 704 | mutex_unlock(&chip->otprom_lock); 705 | 706 | out: 707 | kfree(lbuf); 708 | return ret; 709 | } 710 | static DEVICE_ATTR_RW(otp_rom); 711 | 712 | static ssize_t irq_poll_interval_show(struct device *dev, 713 | struct device_attribute *attr, char *buf) 714 | { 715 | struct usb_interface *intf; 716 | struct usb_device *udev; 717 | struct cp2130_device *chip; 718 | ssize_t ret; 719 | 720 | intf = to_usb_interface(dev); 721 | if (!intf) 722 | return -EFAULT; 723 | 724 | chip = usb_get_intfdata(intf); 725 | if (!chip) 726 | return -EFAULT; 727 | 728 | udev = usb_get_dev(interface_to_usbdev(intf)); 729 | if (!udev) 730 | return -EFAULT; 731 | 732 | ret = sprintf(buf, "%d us\n", chip->irq_poll_interval); 733 | 734 | return ret; 735 | } 736 | 737 | static ssize_t irq_poll_interval_store(struct device *dev, 738 | struct device_attribute *attr, 739 | const char *buf, size_t count) 740 | { 741 | struct usb_interface *intf; 742 | struct usb_device *udev; 743 | struct cp2130_device *chip; 744 | int ret, interval; 745 | 746 | intf = to_usb_interface(dev); 747 | if (!intf) 748 | return -EFAULT; 749 | 750 | chip = usb_get_intfdata(intf); 751 | if (!chip) 752 | return -EFAULT; 753 | 754 | udev = usb_get_dev(interface_to_usbdev(intf)); 755 | if (!udev) 756 | return -EFAULT; 757 | 758 | ret = kstrtoint(buf, 10, &interval); 759 | 760 | /* we only allow numbers and nothing below 10us */ 761 | if (ret || interval < 10) 762 | return -EINVAL; 763 | 764 | chip->irq_poll_interval = interval; 765 | 766 | return count; 767 | } 768 | static DEVICE_ATTR_RW(irq_poll_interval); 769 | 770 | static int cp2130_transfer_bulk_message(struct spi_master *master, 771 | struct spi_transfer *xfer, 772 | unsigned int pos) 773 | { 774 | int header_size, data_size, len, ret, tx_len; 775 | unsigned int limit; 776 | unsigned int recv_pipe, xmit_pipe; 777 | struct cp2130_device *dev = 778 | (struct cp2130_device*) spi_master_get_devdata(master); 779 | bool first_frame = !pos; 780 | 781 | xmit_pipe = usb_sndbulkpipe(dev->udev, 0x01); 782 | recv_pipe = usb_rcvbulkpipe(dev->udev, 0x82); 783 | 784 | dev_dbg(&master->dev, "recv/xmit pipes: %u / %u", 785 | recv_pipe, xmit_pipe); 786 | 787 | /* if this is the first packet we need to prepare the header, if not 788 | we can use all available space in the packet */ 789 | if (first_frame) { 790 | /* zero the transfer buffer header, this implicitely 791 | initializes the reserved fields */ 792 | memset(dev->usb_xfer, 0, CP2130_BULK_HEADER_SIZE); 793 | 794 | /* init length field */ 795 | *((u32*) (dev->usb_xfer + CP2130_BULK_OFFSET_LENGTH)) = 796 | __cpu_to_le32(xfer->len); 797 | 798 | header_size = CP2130_BULK_HEADER_SIZE; 799 | 800 | /* now set the command type according to the SPI message setup */ 801 | if (xfer->tx_buf && xfer->rx_buf) { 802 | /* Simultaneous SPI write and read */ 803 | limit = CP2130_MAX_USB_PACKET_SIZE - 804 | CP2130_BULK_HEADER_SIZE; 805 | data_size = min(limit, xfer->len - pos); 806 | tx_len = header_size + data_size; 807 | dev->usb_xfer[CP2130_BULK_OFFSET_CMD] = 808 | CP2130_CMD_WRITEREAD; 809 | } else if (xfer->tx_buf) { 810 | /* SPI write only */ 811 | limit = CP2130_MAX_USB_PACKET_SIZE - 812 | CP2130_BULK_HEADER_SIZE; 813 | data_size = min(limit, xfer->len - pos); 814 | tx_len = header_size + data_size; 815 | dev->usb_xfer[CP2130_BULK_OFFSET_CMD] = 816 | CP2130_CMD_WRITE; 817 | } else if (xfer->rx_buf) { 818 | /* SPI read only */ 819 | limit = CP2130_MAX_USB_PACKET_SIZE; 820 | data_size = min(limit, xfer->len - pos); 821 | tx_len = CP2130_BULK_HEADER_SIZE; 822 | dev->usb_xfer[CP2130_BULK_OFFSET_CMD] = 823 | CP2130_CMD_READ; 824 | } 825 | } else { 826 | header_size = 0; 827 | limit = CP2130_MAX_USB_PACKET_SIZE; 828 | data_size = min(limit, xfer->len - pos); 829 | tx_len = header_size + data_size; 830 | } 831 | 832 | /* copy chunk of SPI tx data */ 833 | if (xfer->tx_buf) 834 | memcpy(dev->usb_xfer + header_size, xfer->tx_buf + pos, data_size); 835 | 836 | /* prepare URB and submit sync 837 | CP2130 / AN792 p.7: 'any previous data transfer command 838 | must complete before another data transfer command 839 | is issued', so there is no advantage from using the 840 | async USB API */ 841 | if (xfer->tx_buf && xfer->rx_buf) { 842 | /* simultaneous SPI write and read */ 843 | ret = usb_bulk_msg(dev->udev, xmit_pipe, dev->usb_xfer, 844 | tx_len, &len, 200); 845 | dev_dbg(&master->dev, 846 | "write-read - usb tx phase: ret=%d, wrote %d/%d", 847 | ret, len, tx_len); 848 | if (ret) 849 | goto out; 850 | ret = usb_bulk_msg(dev->udev, recv_pipe, xfer->rx_buf + pos, 851 | data_size, &len, 200); 852 | dev_dbg(&master->dev, 853 | "write-read - usb rx phase: ret=%d, read %d/%d", 854 | ret, len, data_size); 855 | } else if (xfer->tx_buf) { 856 | /* SPI write only */ 857 | ret = usb_bulk_msg(dev->udev, xmit_pipe, dev->usb_xfer, 858 | tx_len, &len, 200); 859 | dev_dbg(&master->dev, 860 | "write - usb tx phase: ret=%d, wrote %d/%d", 861 | ret, len, tx_len); 862 | len -= header_size; 863 | } else if (xfer->rx_buf) { 864 | /* SPI read only */ 865 | if (first_frame) { /* write read request only for first frame */ 866 | ret = usb_bulk_msg(dev->udev, xmit_pipe, dev->usb_xfer, 867 | tx_len, &len, 200); 868 | dev_dbg(&master->dev, 869 | "read - usb tx phase: ret=%d, wrote %d/%d", 870 | ret, len, tx_len); 871 | if (ret) 872 | goto out; 873 | } 874 | ret = usb_bulk_msg(dev->udev, recv_pipe, xfer->rx_buf + pos, 875 | data_size, &len, 200); 876 | dev_dbg(&master->dev, 877 | "read - usb rx phase: ret=%d, read %d/%d", 878 | ret, len, data_size); 879 | } 880 | 881 | out: 882 | return (!ret ? len : ret); 883 | } 884 | 885 | static int cp2130_spi_transfer_one_message(struct spi_master *master, 886 | struct spi_message *mesg) 887 | { 888 | struct spi_transfer *xfer; 889 | struct cp2130_device *dev = 890 | (struct cp2130_device*) spi_master_get_devdata(master); 891 | int ret = 0, chn_id; 892 | struct cp2130_channel *chn; 893 | unsigned int xmit_ctrl_pipe; 894 | unsigned int pos, transfer_delay; 895 | 896 | dev_dbg(&master->dev, "spi transfer one message"); 897 | 898 | /* search for spi setup of this device */ 899 | for (chn_id = 0; chn_id < CP2130_NUM_GPIOS; chn_id++) { 900 | chn = &dev->chn_configs[chn_id]; 901 | if (chn->chip == mesg->spi) 902 | break; 903 | } 904 | 905 | if (chn_id == CP2130_NUM_GPIOS) { 906 | ret = -ENODEV; 907 | goto out_notfound; 908 | } 909 | 910 | mutex_lock(&dev->usb_bus_lock); 911 | 912 | xmit_ctrl_pipe = usb_sndctrlpipe(dev->udev, 0); 913 | if (chn_id != dev->current_channel) { 914 | dev_dbg(&dev->udev->dev, "load setup for channel %d", chn_id); 915 | dev->usb_xfer[0] = chn_id; 916 | dev->usb_xfer[1] = chn->cs_en; 917 | ret = usb_control_msg( 918 | dev->udev, xmit_ctrl_pipe, 919 | CP2130_BREQ_SET_GPIO_CS, 920 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 921 | 0, 0, 922 | dev->usb_xfer, 2, 200); 923 | if (ret != 2) 924 | goto out; 925 | 926 | dev->current_channel = chn_id; 927 | } 928 | 929 | /* iterate through all transfers */ 930 | list_for_each_entry(xfer, &mesg->transfers, transfer_list) { 931 | dev_dbg(&master->dev, "spi transfer stats: %p, %p, %d", 932 | xfer->tx_buf, xfer->rx_buf, xfer->len); 933 | 934 | /* empty transfer */ 935 | if (!xfer->tx_buf && !xfer->rx_buf) { 936 | udelay(xfer->delay_usecs); 937 | continue; 938 | } 939 | 940 | /* be prepared for messages > 64 byte */ 941 | pos = 0; 942 | 943 | /* split the xfer data into chunks for 64 bytes and submit */ 944 | while (pos < xfer->len) { 945 | ret = cp2130_transfer_bulk_message(master, xfer, pos); 946 | 947 | /* wait until all bytes are sent on the SPI bus */ 948 | transfer_delay = cp2130_spi_speed_to_nsec( 949 | chn->clock_freq) /* nsec per bit */ 950 | * ret * 8 /* number of bits */ 951 | * 2 /* headroom */ 952 | / 1000 /* to usec */; 953 | udelay(transfer_delay); 954 | 955 | if (ret < 0) 956 | break; 957 | pos += ret; 958 | } 959 | udelay(xfer->delay_usecs); 960 | mesg->actual_length += xfer->len; 961 | } 962 | 963 | out: 964 | mutex_unlock(&dev->usb_bus_lock); 965 | out_notfound: 966 | ret = (ret < 0) ? ret : 0; 967 | if (ret) 968 | dev_err(&master->dev, "USB transfer failed with %d", ret); 969 | mesg->status = ret; 970 | spi_finalize_current_message(master); /* signal done to queue */ 971 | return ret; 972 | } 973 | 974 | static int cp2130_irq_from_pin(struct cp2130_device *dev, int pin) 975 | { 976 | return dev->irq_chip.virq[pin]; 977 | } 978 | 979 | static void cp2130_update_channel_config(struct work_struct *work) 980 | { 981 | int i; 982 | int ret; 983 | unsigned int xmit_pipe; 984 | struct cp2130_device *dev = container_of(work, 985 | struct cp2130_device, 986 | update_chn_config); 987 | struct cp2130_channel *chn; 988 | 989 | dev_dbg(&dev->udev->dev, "control pipes: %u, %u", 990 | usb_sndctrlpipe(dev->udev, 0), 991 | usb_rcvctrlpipe(dev->udev, 0)); 992 | 993 | xmit_pipe = usb_sndctrlpipe(dev->udev, 0); 994 | 995 | mutex_lock(&dev->chn_config_lock); 996 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 997 | chn = &dev->chn_configs[i]; 998 | if (!chn->updated) 999 | continue; 1000 | 1001 | if (chn->updated > 1) 1002 | continue; 1003 | 1004 | chn->updated++; 1005 | 1006 | dev_dbg(&dev->udev->dev, "update config of channel %d", i); 1007 | dev->usb_xfer[0] = i; 1008 | 1009 | mutex_lock(&dev->usb_bus_lock); 1010 | 1011 | dev_dbg(&dev->udev->dev, "set spi word"); 1012 | dev->usb_xfer[1] = (chn->clock_freq << 0) | 1013 | (chn->cs_pin_mode << 3) | 1014 | (chn->polarity << 4) | 1015 | (chn->clock_phase << 5); 1016 | 1017 | ret = usb_control_msg( 1018 | dev->udev, xmit_pipe, 1019 | CP2130_BREQ_SET_SPI_WORD, 1020 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 1021 | 0, 0, 1022 | dev->usb_xfer, 2, 200); 1023 | if (ret < 2) 1024 | goto error_unlock; 1025 | 1026 | dev_dbg(&dev->udev->dev, "set spi delay"); 1027 | dev->usb_xfer[1] = chn->delay_mask; 1028 | 1029 | dev->usb_xfer[2] = (chn->inter_byte_delay & 0xff00) >> 8; 1030 | dev->usb_xfer[3] = (chn->inter_byte_delay & 0x00ff) >> 0; 1031 | 1032 | dev->usb_xfer[4] = (chn->post_assert_delay & 0xff00) >> 8; 1033 | dev->usb_xfer[5] = (chn->post_assert_delay & 0x00ff) >> 0; 1034 | 1035 | dev->usb_xfer[6] = (chn->pre_deassert_delay & 0xff00) >> 8; 1036 | dev->usb_xfer[7] = (chn->pre_deassert_delay & 0x00ff) >> 0; 1037 | ret = usb_control_msg( 1038 | dev->udev, xmit_pipe, 1039 | CP2130_BREQ_SET_SPI_DELAY, 1040 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 1041 | 0, 0, 1042 | dev->usb_xfer, 8, 200); 1043 | if (ret < 8) 1044 | goto error_unlock; 1045 | 1046 | /* configure irq pin as input if required */ 1047 | if (chn->irq_pin >= 0) { 1048 | dev->usb_xfer[0] = chn->irq_pin; 1049 | dev->usb_xfer[1] = 0; /* input */ 1050 | dev->usb_xfer[2] = 0; /* value, ignored for input */ 1051 | ret = usb_control_msg( 1052 | dev->udev, xmit_pipe, 1053 | CP2130_BREQ_SET_GPIO_MODE, 1054 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 1055 | 0, 0, 1056 | dev->usb_xfer, 3, 200); 1057 | if (ret < 3) 1058 | goto error_unlock; 1059 | } 1060 | 1061 | mutex_unlock(&dev->usb_bus_lock); 1062 | 1063 | dev_dbg(&dev->udev->dev, "try register %s", chn->modalias); 1064 | 1065 | chn->chip = spi_alloc_device(dev->spi_master); 1066 | if (!chn->chip) 1067 | goto error; 1068 | 1069 | chn->chip->max_speed_hz = dev->spi_master->max_speed_hz; 1070 | chn->chip->chip_select = i; 1071 | chn->chip->mode = (chn->polarity << 1) | chn->clock_phase; 1072 | chn->chip->bits_per_word = 8; /* we can only do this */ 1073 | chn->chip->irq = cp2130_irq_from_pin(dev, chn->irq_pin); 1074 | 1075 | chn->chip->dev.platform_data = chn->pdata; 1076 | 1077 | dev_dbg(&dev->udev->dev, "initialized %s chip", chn->modalias); 1078 | strncpy(chn->chip->modalias, chn->modalias, 1079 | sizeof(chn->chip->modalias)); 1080 | 1081 | ret = spi_add_device(chn->chip); 1082 | if (ret) 1083 | goto error; 1084 | 1085 | dev_dbg(&dev->udev->dev, "%s probe complete", chn->modalias); 1086 | } 1087 | mutex_unlock(&dev->chn_config_lock); 1088 | 1089 | schedule_work(&dev->read_chn_config); 1090 | return; 1091 | 1092 | error_unlock: 1093 | mutex_unlock(&dev->usb_bus_lock); 1094 | 1095 | error: 1096 | mutex_unlock(&dev->chn_config_lock); 1097 | dev_err(&dev->udev->dev, "failed to configure channel %d", i); 1098 | } 1099 | 1100 | static void cp2130_read_channel_config(struct work_struct *work) 1101 | { 1102 | int i; 1103 | int ret; 1104 | unsigned int recv_pipe; 1105 | struct cp2130_device *dev = container_of(work, 1106 | struct cp2130_device, 1107 | read_chn_config); 1108 | struct cp2130_channel *chn; 1109 | 1110 | dev_dbg(&dev->udev->dev, "control pipes: %u, %u", 1111 | usb_sndctrlpipe(dev->udev, 0), 1112 | usb_rcvctrlpipe(dev->udev, 0)); 1113 | 1114 | recv_pipe = usb_rcvctrlpipe(dev->udev, 0); 1115 | 1116 | mutex_lock(&dev->chn_config_lock); 1117 | mutex_lock(&dev->usb_bus_lock); 1118 | dev_dbg(&dev->udev->dev, "read channel configs"); 1119 | 1120 | dev_dbg(&dev->udev->dev, "get spi word"); 1121 | ret = usb_control_msg( 1122 | dev->udev, recv_pipe, 1123 | CP2130_BREQ_GET_SPI_WORD, 1124 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 1125 | 0, 0, 1126 | dev->usb_xfer, 11, 200); 1127 | 1128 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 1129 | chn = &dev->chn_configs[i]; 1130 | 1131 | chn->clock_freq = dev->usb_xfer[i] & 7; 1132 | chn->cs_pin_mode = !!(dev->usb_xfer[i] & 8); 1133 | chn->polarity = !!(dev->usb_xfer[i] & 16); 1134 | chn->clock_phase = !!(dev->usb_xfer[i] & 32); 1135 | } 1136 | 1137 | dev_dbg(&dev->udev->dev, "get delays"); 1138 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 1139 | ret = usb_control_msg( 1140 | dev->udev, recv_pipe, 1141 | CP2130_BREQ_GET_SPI_DELAY, 1142 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 1143 | 0, i, 1144 | dev->usb_xfer, 8, 200); 1145 | 1146 | chn = &dev->chn_configs[i]; 1147 | 1148 | chn->delay_mask = dev->usb_xfer[1]; 1149 | chn->inter_byte_delay = dev->usb_xfer[2] << 8; 1150 | chn->inter_byte_delay |= dev->usb_xfer[3] & 0xff; 1151 | chn->post_assert_delay = dev->usb_xfer[4] << 8; 1152 | chn->post_assert_delay |= dev->usb_xfer[5] & 0xff; 1153 | chn->pre_deassert_delay = dev->usb_xfer[6] << 8; 1154 | chn->pre_deassert_delay |= dev->usb_xfer[7] & 0xff; 1155 | } 1156 | 1157 | mutex_unlock(&dev->usb_bus_lock); 1158 | mutex_unlock(&dev->chn_config_lock); 1159 | } 1160 | 1161 | static void cp2130_update_otprom(struct work_struct *work) 1162 | { 1163 | int i; 1164 | struct cp2130_device *dev = container_of(work, 1165 | struct cp2130_device, 1166 | update_otprom); 1167 | int ret; 1168 | unsigned int xmit_pipe; 1169 | 1170 | xmit_pipe = usb_sndctrlpipe(dev->udev, 0); 1171 | 1172 | mutex_lock(&dev->otprom_lock); 1173 | 1174 | for (i = 0; i < CP2130_NUM_GPIOS; i++) 1175 | dev->usb_xfer[i] = dev->otprom_config.pin_config[i]; 1176 | 1177 | mutex_lock(&dev->usb_bus_lock); 1178 | 1179 | ret = usb_control_msg( 1180 | dev->udev, xmit_pipe, 1181 | CP2130_BREQ_SET_PIN_CONFIG, 1182 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 1183 | CP2130_BREQ_MEMORY_KEY, 0, 1184 | dev->usb_xfer, 20, 200); 1185 | 1186 | if (ret) 1187 | dev_err(&dev->udev->dev, "error writing OTP ROM pin config"); 1188 | 1189 | mutex_unlock(&dev->usb_bus_lock); 1190 | mutex_unlock(&dev->otprom_lock); 1191 | 1192 | schedule_work(&dev->read_otprom); 1193 | } 1194 | 1195 | static void cp2130_read_otprom(struct work_struct *work) 1196 | { 1197 | int i; 1198 | int ret; 1199 | unsigned int recv_pipe; 1200 | struct cp2130_device *dev = container_of(work, 1201 | struct cp2130_device, 1202 | read_otprom); 1203 | 1204 | dev_dbg(&dev->udev->dev, "control pipes: %u, %u", 1205 | usb_sndctrlpipe(dev->udev, 0), 1206 | usb_rcvctrlpipe(dev->udev, 0)); 1207 | 1208 | recv_pipe = usb_rcvctrlpipe(dev->udev, 0); 1209 | 1210 | mutex_lock(&dev->otprom_lock); 1211 | mutex_lock(&dev->usb_bus_lock); 1212 | dev_dbg(&dev->udev->dev, "read OTP ROM"); 1213 | 1214 | dev_dbg(&dev->udev->dev, "get lock byte"); 1215 | ret = usb_control_msg( 1216 | dev->udev, recv_pipe, 1217 | CP2130_BREQ_GET_LOCK_BYTE, 1218 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 1219 | 0, 0, 1220 | dev->usb_xfer, 2, 200); 1221 | dev_info(&dev->udev->dev, "lock byte %02X %02X", 1222 | dev->usb_xfer[0] & 0xff, dev->usb_xfer[1] & 0x0f); 1223 | dev->otprom_config.lock_byte = dev->usb_xfer[0] & 0xff; 1224 | dev->otprom_config.lock_byte |= (dev->usb_xfer[1] & 0x0f) << 8; 1225 | 1226 | dev_dbg(&dev->udev->dev, "get pin config"); 1227 | ret = usb_control_msg( 1228 | dev->udev, recv_pipe, 1229 | CP2130_BREQ_GET_PIN_CONFIG, 1230 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 1231 | 0, 0, 1232 | dev->usb_xfer, 20, 200); 1233 | 1234 | for (i = 0; i < CP2130_NUM_GPIOS; ++i) { 1235 | dev_info(&dev->udev->dev, "pin %d: %02X", 1236 | i, dev->usb_xfer[i]); 1237 | dev->otprom_config.pin_config[i] = dev->usb_xfer[i]; 1238 | } 1239 | dev->otprom_config.suspend_level = 1240 | (dev->usb_xfer[i] << 8) | dev->usb_xfer[i + 1]; 1241 | i += 2; 1242 | dev->otprom_config.suspend_mode = 1243 | (dev->usb_xfer[i] << 8) | dev->usb_xfer[i + 1]; 1244 | i += 2; 1245 | dev->otprom_config.wakeup_mask = 1246 | (dev->usb_xfer[i] << 8) | dev->usb_xfer[i + 1]; 1247 | i += 2; 1248 | dev->otprom_config.wakeup_match = 1249 | (dev->usb_xfer[i] << 8) | dev->usb_xfer[i + 1]; 1250 | i += 2; 1251 | dev->otprom_config.divider = dev->usb_xfer[i]; 1252 | 1253 | mutex_unlock(&dev->usb_bus_lock); 1254 | mutex_unlock(&dev->otprom_lock); 1255 | } 1256 | 1257 | static void cp2130_read_gpios(struct work_struct *work) 1258 | { 1259 | unsigned int recv_pipe; 1260 | struct cp2130_device *dev = container_of(work, 1261 | struct cp2130_device, 1262 | irq_work); 1263 | int i, set; 1264 | unsigned long flags; 1265 | 1266 | loop: 1267 | recv_pipe = usb_rcvctrlpipe(dev->udev, 0); 1268 | 1269 | dev_dbg(&dev->udev->dev, "start read gpios"); 1270 | 1271 | mutex_lock(&dev->usb_bus_lock); 1272 | 1273 | i = usb_control_msg( 1274 | dev->udev, recv_pipe, 1275 | CP2130_BREQ_GET_GPIO_VALUES, 1276 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 1277 | 0, 0, 1278 | dev->usb_xfer, 2, 200); 1279 | 1280 | dev->gpio_states[0] = dev->usb_xfer[0]; 1281 | dev->gpio_states[1] = dev->usb_xfer[1]; 1282 | 1283 | mutex_unlock(&dev->usb_bus_lock); 1284 | 1285 | if (i < 2) { 1286 | dev_err(&dev->udev->dev, "failed to read gpios"); 1287 | goto next; 1288 | } 1289 | 1290 | dev_dbg(&dev->udev->dev, "read gpios 1: %02X", 1291 | dev->gpio_states[1] & 0xff & ~(1 | 2 | 4)); 1292 | dev_dbg(&dev->udev->dev, "read gpios 2: %02X", 1293 | dev->gpio_states[0] & 0xff & ~(2 | 128)); 1294 | 1295 | for (i = 0; i < CP2130_NUM_GPIOS; ++i) { 1296 | if (!(dev->irq_chip.irq_mask & (1 << i))) 1297 | continue; 1298 | 1299 | switch (i) { 1300 | case 0: 1301 | case 1: 1302 | case 2: 1303 | case 3: 1304 | case 4: 1305 | set = dev->gpio_states[1] & (8 << i); 1306 | break; 1307 | case 5: 1308 | set = dev->gpio_states[0] & (1 << 0); 1309 | break; 1310 | case 6: 1311 | case 7: 1312 | case 8: 1313 | case 9: 1314 | case 10: 1315 | set = dev->gpio_states[0] & (4 << (i - 6)); 1316 | break; 1317 | } 1318 | 1319 | if (!set) { 1320 | dev_dbg(&dev->udev->dev, "issue irq on %d", i); 1321 | local_irq_save(flags); 1322 | generic_handle_irq(dev->irq_chip.virq[i]); 1323 | local_irq_restore(flags); 1324 | } 1325 | } 1326 | 1327 | next: 1328 | if (dev->irq_poll_interval < 0) 1329 | return; 1330 | 1331 | usleep_range(dev->irq_poll_interval, dev->irq_poll_interval + 20); 1332 | goto loop; 1333 | } 1334 | 1335 | static void cp2130_gpio_irq_mask(struct irq_data *data) 1336 | { 1337 | struct cp2130_gpio_irq *irq_dev = irq_data_get_irq_chip_data(data); 1338 | struct cp2130_device *dev 1339 | = container_of(irq_dev, struct cp2130_device, irq_chip); 1340 | 1341 | dev_dbg(&dev->udev->dev, "irq mask %lu", data->hwirq); 1342 | irq_dev->irq_mask &= ~(1 << data->hwirq); 1343 | } 1344 | 1345 | static void cp2130_gpio_irq_unmask(struct irq_data *data) 1346 | { 1347 | struct cp2130_gpio_irq *irq_dev = irq_data_get_irq_chip_data(data); 1348 | struct cp2130_device *dev 1349 | = container_of(irq_dev, struct cp2130_device, irq_chip); 1350 | 1351 | dev_dbg(&dev->udev->dev, "irq unmask %lu", data->hwirq); 1352 | irq_dev->irq_mask |= 1 << data->hwirq; 1353 | } 1354 | 1355 | static int cp2130_gpio_irq_set_type(struct irq_data *data, unsigned int type) 1356 | { 1357 | return 0; 1358 | } 1359 | 1360 | static void cp2130_gpio_irq_bus_lock(struct irq_data *data) 1361 | { 1362 | struct cp2130_gpio_irq *irq_dev = irq_data_get_irq_chip_data(data); 1363 | mutex_lock(&irq_dev->irq_lock); 1364 | } 1365 | 1366 | static void cp2130_gpio_irq_bus_unlock(struct irq_data *data) 1367 | { 1368 | struct cp2130_gpio_irq *irq_dev = irq_data_get_irq_chip_data(data); 1369 | mutex_unlock(&irq_dev->irq_lock); 1370 | } 1371 | 1372 | static struct irq_chip cp2130_gpio_irq_chip = { 1373 | .name = "gpio-cp2130", 1374 | .irq_mask = cp2130_gpio_irq_mask, 1375 | .irq_unmask = cp2130_gpio_irq_unmask, 1376 | .irq_set_type = cp2130_gpio_irq_set_type, 1377 | .irq_bus_lock = cp2130_gpio_irq_bus_lock, 1378 | .irq_bus_sync_unlock = cp2130_gpio_irq_bus_unlock, 1379 | }; 1380 | 1381 | static int cp2130_gpio_irq_map(struct irq_domain *domain, unsigned int irq, 1382 | irq_hw_number_t hwirq) 1383 | { 1384 | irq_set_chip_data(irq, domain->host_data); 1385 | irq_set_chip(irq, &cp2130_gpio_irq_chip); 1386 | irq_set_chip_and_handler(irq, &cp2130_gpio_irq_chip, handle_simple_irq); 1387 | irq_set_noprobe(irq); 1388 | return 0; 1389 | } 1390 | 1391 | static const struct irq_domain_ops cp2130_gpio_irq_domain_ops = { 1392 | .map = cp2130_gpio_irq_map, 1393 | }; 1394 | 1395 | static void cp2130_gpio_irq_remove(struct cp2130_device *dev); 1396 | 1397 | static int cp2130_gpio_irq_probe(struct cp2130_device *dev) 1398 | { 1399 | struct cp2130_gpio_irq *irq_dev = &dev->irq_chip; 1400 | int i; 1401 | 1402 | mutex_init(&irq_dev->irq_lock); 1403 | 1404 | irq_dev->irq_domain = irq_domain_add_linear( 1405 | dev->udev->dev.of_node, CP2130_NUM_GPIOS, 1406 | &cp2130_gpio_irq_domain_ops, irq_dev); 1407 | 1408 | if (!irq_dev->irq_domain) { 1409 | dev_err(&dev->udev->dev, "failed to register IRQ domain"); 1410 | return -ENOMEM; 1411 | } 1412 | 1413 | irq_dev->irq_mask = 0; 1414 | for (i = 0; i < CP2130_NUM_GPIOS; ++i) { 1415 | irq_dev->virq[i] = 1416 | irq_create_mapping(irq_dev->irq_domain, i); 1417 | dev_dbg(&dev->udev->dev, "created virtual irq %d", 1418 | irq_dev->virq[i]); 1419 | } 1420 | 1421 | INIT_WORK(&dev->irq_work, cp2130_read_gpios); 1422 | schedule_work(&dev->irq_work); 1423 | 1424 | return 0; 1425 | } 1426 | 1427 | static void cp2130_gpio_irq_remove(struct cp2130_device *dev) 1428 | { 1429 | int i = 0; 1430 | 1431 | if (!dev->irq_chip.irq_domain) 1432 | return; 1433 | 1434 | for (i = 0; i < CP2130_NUM_GPIOS; ++i) { 1435 | irq_dispose_mapping(dev->irq_chip.virq[i]); 1436 | } 1437 | 1438 | irq_domain_remove(dev->irq_chip.irq_domain); 1439 | } 1440 | 1441 | static int cp2130_gpio_direction_input(struct gpio_chip *gc, unsigned off) 1442 | { 1443 | struct cp2130_device *dev = gpiochip_get_data(gc); 1444 | int ret; 1445 | unsigned int xmit_pipe; 1446 | 1447 | xmit_pipe = usb_sndctrlpipe(dev->udev, 0); 1448 | 1449 | mutex_lock(&dev->usb_bus_lock); 1450 | 1451 | dev->usb_xfer[0] = off; 1452 | dev->usb_xfer[1] = 0; /* input */ 1453 | dev->usb_xfer[2] = 0; /* value, ignored for input */ 1454 | ret = usb_control_msg( 1455 | dev->udev, xmit_pipe, 1456 | CP2130_BREQ_SET_GPIO_MODE, 1457 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 1458 | 0, 0, 1459 | dev->usb_xfer, 3, 200); 1460 | 1461 | mutex_unlock(&dev->usb_bus_lock); 1462 | 1463 | return (ret == 3) ? 0 : -EIO; 1464 | } 1465 | 1466 | static int cp2130_gpio_direction_output(struct gpio_chip *gc, unsigned off, 1467 | int val) 1468 | { 1469 | struct cp2130_device *dev = gpiochip_get_data(gc); 1470 | int ret; 1471 | unsigned int xmit_pipe; 1472 | 1473 | xmit_pipe = usb_sndctrlpipe(dev->udev, 0); 1474 | 1475 | mutex_lock(&dev->usb_bus_lock); 1476 | 1477 | dev->usb_xfer[0] = off; 1478 | dev->usb_xfer[1] = 2; /* push-pull output */ 1479 | dev->usb_xfer[2] = val; /* state */ 1480 | ret = usb_control_msg( 1481 | dev->udev, xmit_pipe, 1482 | CP2130_BREQ_SET_GPIO_MODE, 1483 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, 1484 | 0, 0, 1485 | dev->usb_xfer, 3, 200); 1486 | 1487 | mutex_unlock(&dev->usb_bus_lock); 1488 | 1489 | return (ret == 3) ? 0 : -EIO; 1490 | } 1491 | 1492 | static int cp2130_gpio_get_value(struct gpio_chip *gc, unsigned off) 1493 | { 1494 | struct cp2130_device *dev = gpiochip_get_data(gc); 1495 | int set; 1496 | 1497 | switch (off) { 1498 | case 0: 1499 | case 1: 1500 | case 2: 1501 | case 3: 1502 | case 4: 1503 | set = !!(dev->gpio_states[1] & (8 << off)); 1504 | break; 1505 | case 5: 1506 | set = !!(dev->gpio_states[0] & (1 << 0)); 1507 | break; 1508 | case 6: 1509 | case 7: 1510 | case 8: 1511 | case 9: 1512 | case 10: 1513 | set = !!(dev->gpio_states[0] & (4 << (off - 6))); 1514 | break; 1515 | default: 1516 | set = -EINVAL; 1517 | break; 1518 | } 1519 | return set; 1520 | } 1521 | 1522 | static void cp2130_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) 1523 | { 1524 | cp2130_gpio_direction_output(gc, off, val); 1525 | } 1526 | 1527 | static const char* cp2130_gpio_names[] = { "........-_cs0", 1528 | "........-_cs1", 1529 | "........-_cs2", 1530 | "........-_rtr", 1531 | "........-event_counter", 1532 | "........-clk_out", 1533 | "........-gpi", 1534 | "........-gpo", 1535 | "........-activity", 1536 | "........-suspend", 1537 | "........-_suspend", 1538 | }; 1539 | 1540 | static int cp2130_probe(struct usb_interface *intf, 1541 | const struct usb_device_id *id) 1542 | { 1543 | struct usb_device *udev = usb_get_dev(interface_to_usbdev(intf)); 1544 | struct cp2130_device *dev; 1545 | struct spi_master *spi_master = NULL; 1546 | struct gpio_chip *gc; 1547 | struct usb_host_interface *iface_desc = intf->cur_altsetting; 1548 | struct usb_endpoint_descriptor *endpoint; 1549 | int i, ret; 1550 | 1551 | ret = -ENOMEM; 1552 | 1553 | printk(KERN_DEBUG "cp2130 probe\n"); 1554 | 1555 | if (!udev) 1556 | return -ENODEV; 1557 | 1558 | dev = kzalloc(sizeof(struct cp2130_device), GFP_KERNEL); 1559 | if (!dev) 1560 | goto err_out; 1561 | dev->usb_xfer = kmalloc(CP2130_MAX_USB_PACKET_SIZE, GFP_KERNEL); 1562 | if (!dev->usb_xfer) 1563 | goto err_out; 1564 | 1565 | dev->udev = udev; 1566 | dev->intf = intf; 1567 | 1568 | mutex_init(&dev->usb_bus_lock); 1569 | mutex_init(&dev->chn_config_lock); 1570 | mutex_init(&dev->otprom_lock); 1571 | 1572 | dev->current_channel = -1; 1573 | 1574 | usb_set_intfdata(intf, dev); 1575 | 1576 | for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 1577 | endpoint = &iface_desc->endpoint[i].desc; 1578 | dev_dbg(&udev->dev, "ep addr: 0x%02x", 1579 | endpoint->bEndpointAddress); 1580 | if (usb_endpoint_is_bulk_in(endpoint)) 1581 | dev_dbg(&udev->dev, "bulk in ep addr: 0x%02x", 1582 | endpoint->bEndpointAddress); 1583 | if (usb_endpoint_is_bulk_out(endpoint)) 1584 | dev_dbg(&udev->dev, "bulk out ep addr: 0x%02x", 1585 | endpoint->bEndpointAddress); 1586 | } 1587 | 1588 | spi_master = spi_alloc_master(&udev->dev, sizeof(void*)); 1589 | if (!spi_master) 1590 | goto err_out; 1591 | 1592 | spi_master_set_devdata(spi_master, (void*) dev); 1593 | 1594 | spi_master->min_speed_hz = 93 * 1000 + 800; /* 93.8kHz */ 1595 | spi_master->max_speed_hz = 12 * 1000 * 1000; /* 12 MHz */ 1596 | 1597 | spi_master->bus_num = -1; /* dynamically assigned */ 1598 | spi_master->num_chipselect = CP2130_NUM_GPIOS; 1599 | spi_master->mode_bits = 1600 | SPI_MODE_0 | SPI_MODE_1 | SPI_MODE_2 | SPI_MODE_3; 1601 | 1602 | spi_master->flags = 0; 1603 | spi_master->setup = cp2130_spi_setup; 1604 | spi_master->cleanup = cp2130_spi_cleanup; 1605 | spi_master->transfer_one_message = cp2130_spi_transfer_one_message; 1606 | 1607 | ret = spi_register_master(spi_master); 1608 | 1609 | if (ret) { 1610 | dev_err(&udev->dev, "failed to register SPI master"); 1611 | spi_master_put(spi_master); 1612 | dev->spi_master = NULL; 1613 | goto err_out; 1614 | } 1615 | 1616 | dev->spi_master = spi_master; 1617 | dev_dbg(&udev->dev, "registered SPI master"); 1618 | 1619 | /* now enable the gpio chip */ 1620 | gc = &dev->gpio_chip; 1621 | gc->direction_input = cp2130_gpio_direction_input; 1622 | gc->direction_output = cp2130_gpio_direction_output; 1623 | gc->get = cp2130_gpio_get_value; 1624 | gc->set = cp2130_gpio_set_value; 1625 | gc->can_sleep = true; 1626 | 1627 | gc->base = -1; /* auto */ 1628 | gc->ngpio = CP2130_NUM_GPIOS; 1629 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 1630 | dev->gpio_names[i] = kstrdup(cp2130_gpio_names[i], GFP_KERNEL); 1631 | memcpy(dev->gpio_names[i], 1632 | dev_name(&spi_master->dev), 3 + 5 /* spixxxxx */); 1633 | } 1634 | gc->names = (const char**) dev->gpio_names; 1635 | gc->label = dev_name(&spi_master->dev); 1636 | gc->owner = THIS_MODULE; 1637 | 1638 | ret = gpiochip_add_data(&dev->gpio_chip, dev); 1639 | if (ret) 1640 | dev_err(&udev->dev, "failed to register gpio chip"); 1641 | 1642 | /* start irq polling */ 1643 | dev->irq_poll_interval = CP2130_IRQ_POLL_INTERVAL; 1644 | cp2130_gpio_irq_probe(dev); 1645 | dev_dbg(&udev->dev, "registered irq chip"); 1646 | 1647 | /* create sysfs files */ 1648 | ret = device_create_file(&intf->dev, 1649 | &dev_attr_channel_config); 1650 | if (ret) 1651 | dev_err(&udev->dev, 1652 | "failed to create channel_config sysfs entry"); 1653 | 1654 | ret = device_create_file(&intf->dev, 1655 | &dev_attr_channel_pdata); 1656 | if (ret) 1657 | dev_err(&udev->dev, 1658 | "failed to create channel_pdata sysfs entry"); 1659 | 1660 | ret = device_create_file(&intf->dev, 1661 | &dev_attr_otp_rom); 1662 | if (ret) 1663 | dev_err(&udev->dev, 1664 | "failed to create otp_rom sysfs entry"); 1665 | 1666 | ret = device_create_file(&intf->dev, 1667 | &dev_attr_irq_poll_interval); 1668 | if (ret) 1669 | dev_err(&udev->dev, 1670 | "failed to create irq_poll_interval sysfs entry"); 1671 | 1672 | INIT_WORK(&dev->update_chn_config, cp2130_update_channel_config); 1673 | INIT_WORK(&dev->read_chn_config, cp2130_read_channel_config); 1674 | INIT_WORK(&dev->update_otprom, cp2130_update_otprom); 1675 | INIT_WORK(&dev->read_otprom, cp2130_read_otprom); 1676 | schedule_work(&dev->read_chn_config); 1677 | schedule_work(&dev->read_otprom); 1678 | 1679 | return 0; 1680 | 1681 | err_out: 1682 | if (spi_master) 1683 | spi_unregister_master(spi_master); 1684 | if (dev) { 1685 | if (dev->usb_xfer) 1686 | kfree(dev->usb_xfer); 1687 | kfree(dev); 1688 | } 1689 | 1690 | return ret; 1691 | } 1692 | 1693 | static void cp2130_disconnect(struct usb_interface *intf) 1694 | { 1695 | struct cp2130_device *dev = usb_get_intfdata(intf); 1696 | int i = dev->irq_poll_interval; 1697 | 1698 | dev->irq_poll_interval = -1; 1699 | usleep_range(i, i + 100); /* wait for worker to complete */ 1700 | 1701 | /* Remove all devices (if any) attached to the SPI bus */ 1702 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 1703 | if (dev->chn_configs[i].chip) { 1704 | spi_unregister_device(dev->chn_configs[i].chip); 1705 | } 1706 | } 1707 | 1708 | cp2130_gpio_irq_remove(dev); 1709 | gpiochip_remove_(&dev->gpio_chip); 1710 | for (i = 0; i < CP2130_NUM_GPIOS; i++) { 1711 | struct cp2130_channel *chn_cfg = &dev->chn_configs[i]; 1712 | kfree(dev->gpio_names[i]); 1713 | 1714 | if (chn_cfg->pdata) { 1715 | kfree(chn_cfg->pdata); 1716 | chn_cfg->pdata = NULL; 1717 | } 1718 | } 1719 | 1720 | /* remove sysfs files */ 1721 | device_remove_file(&intf->dev, 1722 | &dev_attr_channel_config); 1723 | device_remove_file(&intf->dev, 1724 | &dev_attr_channel_pdata); 1725 | device_remove_file(&intf->dev, 1726 | &dev_attr_otp_rom); 1727 | device_remove_file(&intf->dev, 1728 | &dev_attr_irq_poll_interval); 1729 | 1730 | spi_unregister_master(dev->spi_master); 1731 | 1732 | kfree(dev->usb_xfer); 1733 | kfree(dev); 1734 | } 1735 | 1736 | module_init(cp2130_init); 1737 | module_exit(cp2130_exit); 1738 | MODULE_AUTHOR("Jochen Henneberg "); 1739 | MODULE_DESCRIPTION("Silicon Labs CP2130 single chip USB-to-SPI brigde"); 1740 | MODULE_LICENSE("GPL"); 1741 | 1742 | MODULE_DEVICE_TABLE(usb, cp2130_devices); 1743 | --------------------------------------------------------------------------------