1 /* 2 * Siano core API module 3 * 4 * This file contains implementation for the interface to sms core component 5 * 6 * author: Uri Shkolnik 7 * 8 * Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation; 13 * 14 * Software distributed under the License is distributed on an "AS IS" 15 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 16 * 17 * See the GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24 #include <linux/kernel.h> 25 #include <linux/init.h> 26 #include <linux/module.h> 27 #include <linux/moduleparam.h> 28 #include <linux/dma-mapping.h> 29 #include <linux/delay.h> 30 #include <linux/io.h> 31 #include <linux/slab.h> 32 33 #include <linux/firmware.h> 34 #include <linux/wait.h> 35 #include <asm/byteorder.h> 36 37 #include "smscoreapi.h" 38 #include "sms-cards.h" 39 #include "smsir.h" 40 #include "smsendian.h" 41 42 static int sms_dbg; 43 module_param_named(debug, sms_dbg, int, 0644); 44 MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))"); 45 46 struct smscore_device_notifyee_t { 47 struct list_head entry; 48 hotplug_t hotplug; 49 }; 50 51 struct smscore_idlist_t { 52 struct list_head entry; 53 int id; 54 int data_type; 55 }; 56 57 struct smscore_client_t { 58 struct list_head entry; 59 struct smscore_device_t *coredev; 60 void *context; 61 struct list_head idlist; 62 onresponse_t onresponse_handler; 63 onremove_t onremove_handler; 64 }; 65 66 void smscore_set_board_id(struct smscore_device_t *core, int id) 67 { 68 core->board_id = id; 69 } 70 71 int smscore_led_state(struct smscore_device_t *core, int led) 72 { 73 if (led >= 0) 74 core->led_state = led; 75 return core->led_state; 76 } 77 EXPORT_SYMBOL_GPL(smscore_set_board_id); 78 79 int smscore_get_board_id(struct smscore_device_t *core) 80 { 81 return core->board_id; 82 } 83 EXPORT_SYMBOL_GPL(smscore_get_board_id); 84 85 struct smscore_registry_entry_t { 86 struct list_head entry; 87 char devpath[32]; 88 int mode; 89 enum sms_device_type_st type; 90 }; 91 92 static struct list_head g_smscore_notifyees; 93 static struct list_head g_smscore_devices; 94 static struct mutex g_smscore_deviceslock; 95 96 static struct list_head g_smscore_registry; 97 static struct mutex g_smscore_registrylock; 98 99 static int default_mode = 4; 100 101 module_param(default_mode, int, 0644); 102 MODULE_PARM_DESC(default_mode, "default firmware id (device mode)"); 103 104 static struct smscore_registry_entry_t *smscore_find_registry(char *devpath) 105 { 106 struct smscore_registry_entry_t *entry; 107 struct list_head *next; 108 109 kmutex_lock(&g_smscore_registrylock); 110 for (next = g_smscore_registry.next; 111 next != &g_smscore_registry; 112 next = next->next) { 113 entry = (struct smscore_registry_entry_t *) next; 114 if (!strcmp(entry->devpath, devpath)) { 115 kmutex_unlock(&g_smscore_registrylock); 116 return entry; 117 } 118 } 119 entry = kmalloc(sizeof(struct smscore_registry_entry_t), GFP_KERNEL); 120 if (entry) { 121 entry->mode = default_mode; 122 strcpy(entry->devpath, devpath); 123 list_add(&entry->entry, &g_smscore_registry); 124 } else 125 sms_err("failed to create smscore_registry."); 126 kmutex_unlock(&g_smscore_registrylock); 127 return entry; 128 } 129 130 int smscore_registry_getmode(char *devpath) 131 { 132 struct smscore_registry_entry_t *entry; 133 134 entry = smscore_find_registry(devpath); 135 if (entry) 136 return entry->mode; 137 else 138 sms_err("No registry found."); 139 140 return default_mode; 141 } 142 EXPORT_SYMBOL_GPL(smscore_registry_getmode); 143 144 static enum sms_device_type_st smscore_registry_gettype(char *devpath) 145 { 146 struct smscore_registry_entry_t *entry; 147 148 entry = smscore_find_registry(devpath); 149 if (entry) 150 return entry->type; 151 else 152 sms_err("No registry found."); 153 154 return -1; 155 } 156 157 void smscore_registry_setmode(char *devpath, int mode) 158 { 159 struct smscore_registry_entry_t *entry; 160 161 entry = smscore_find_registry(devpath); 162 if (entry) 163 entry->mode = mode; 164 else 165 sms_err("No registry found."); 166 } 167 168 static void smscore_registry_settype(char *devpath, 169 enum sms_device_type_st type) 170 { 171 struct smscore_registry_entry_t *entry; 172 173 entry = smscore_find_registry(devpath); 174 if (entry) 175 entry->type = type; 176 else 177 sms_err("No registry found."); 178 } 179 180 181 static void list_add_locked(struct list_head *new, struct list_head *head, 182 spinlock_t *lock) 183 { 184 unsigned long flags; 185 186 spin_lock_irqsave(lock, flags); 187 188 list_add(new, head); 189 190 spin_unlock_irqrestore(lock, flags); 191 } 192 193 /** 194 * register a client callback that called when device plugged in/unplugged 195 * NOTE: if devices exist callback is called immediately for each device 196 * 197 * @param hotplug callback 198 * 199 * @return 0 on success, <0 on error. 200 */ 201 int smscore_register_hotplug(hotplug_t hotplug) 202 { 203 struct smscore_device_notifyee_t *notifyee; 204 struct list_head *next, *first; 205 int rc = 0; 206 207 kmutex_lock(&g_smscore_deviceslock); 208 209 notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t), 210 GFP_KERNEL); 211 if (notifyee) { 212 /* now notify callback about existing devices */ 213 first = &g_smscore_devices; 214 for (next = first->next; 215 next != first && !rc; 216 next = next->next) { 217 struct smscore_device_t *coredev = 218 (struct smscore_device_t *) next; 219 rc = hotplug(coredev, coredev->device, 1); 220 } 221 222 if (rc >= 0) { 223 notifyee->hotplug = hotplug; 224 list_add(¬ifyee->entry, &g_smscore_notifyees); 225 } else 226 kfree(notifyee); 227 } else 228 rc = -ENOMEM; 229 230 kmutex_unlock(&g_smscore_deviceslock); 231 232 return rc; 233 } 234 EXPORT_SYMBOL_GPL(smscore_register_hotplug); 235 236 /** 237 * unregister a client callback that called when device plugged in/unplugged 238 * 239 * @param hotplug callback 240 * 241 */ 242 void smscore_unregister_hotplug(hotplug_t hotplug) 243 { 244 struct list_head *next, *first; 245 246 kmutex_lock(&g_smscore_deviceslock); 247 248 first = &g_smscore_notifyees; 249 250 for (next = first->next; next != first;) { 251 struct smscore_device_notifyee_t *notifyee = 252 (struct smscore_device_notifyee_t *) next; 253 next = next->next; 254 255 if (notifyee->hotplug == hotplug) { 256 list_del(¬ifyee->entry); 257 kfree(notifyee); 258 } 259 } 260 261 kmutex_unlock(&g_smscore_deviceslock); 262 } 263 EXPORT_SYMBOL_GPL(smscore_unregister_hotplug); 264 265 static void smscore_notify_clients(struct smscore_device_t *coredev) 266 { 267 struct smscore_client_t *client; 268 269 /* the client must call smscore_unregister_client from remove handler */ 270 while (!list_empty(&coredev->clients)) { 271 client = (struct smscore_client_t *) coredev->clients.next; 272 client->onremove_handler(client->context); 273 } 274 } 275 276 static int smscore_notify_callbacks(struct smscore_device_t *coredev, 277 struct device *device, int arrival) 278 { 279 struct smscore_device_notifyee_t *elem; 280 int rc = 0; 281 282 /* note: must be called under g_deviceslock */ 283 284 list_for_each_entry(elem, &g_smscore_notifyees, entry) { 285 rc = elem->hotplug(coredev, device, arrival); 286 if (rc < 0) 287 break; 288 } 289 290 return rc; 291 } 292 293 static struct 294 smscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer, 295 dma_addr_t common_buffer_phys) 296 { 297 struct smscore_buffer_t *cb = 298 kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL); 299 if (!cb) { 300 sms_info("kmalloc(...) failed"); 301 return NULL; 302 } 303 304 cb->p = buffer; 305 cb->offset_in_common = buffer - (u8 *) common_buffer; 306 cb->phys = common_buffer_phys + cb->offset_in_common; 307 308 return cb; 309 } 310 311 /** 312 * creates coredev object for a device, prepares buffers, 313 * creates buffer mappings, notifies registered hotplugs about new device. 314 * 315 * @param params device pointer to struct with device specific parameters 316 * and handlers 317 * @param coredev pointer to a value that receives created coredev object 318 * 319 * @return 0 on success, <0 on error. 320 */ 321 int smscore_register_device(struct smsdevice_params_t *params, 322 struct smscore_device_t **coredev) 323 { 324 struct smscore_device_t *dev; 325 u8 *buffer; 326 327 dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL); 328 if (!dev) { 329 sms_info("kzalloc(...) failed"); 330 return -ENOMEM; 331 } 332 333 /* init list entry so it could be safe in smscore_unregister_device */ 334 INIT_LIST_HEAD(&dev->entry); 335 336 /* init queues */ 337 INIT_LIST_HEAD(&dev->clients); 338 INIT_LIST_HEAD(&dev->buffers); 339 340 /* init locks */ 341 spin_lock_init(&dev->clientslock); 342 spin_lock_init(&dev->bufferslock); 343 344 /* init completion events */ 345 init_completion(&dev->version_ex_done); 346 init_completion(&dev->data_download_done); 347 init_completion(&dev->trigger_done); 348 init_completion(&dev->init_device_done); 349 init_completion(&dev->reload_start_done); 350 init_completion(&dev->resume_done); 351 init_completion(&dev->gpio_configuration_done); 352 init_completion(&dev->gpio_set_level_done); 353 init_completion(&dev->gpio_get_level_done); 354 init_completion(&dev->ir_init_done); 355 356 /* Buffer management */ 357 init_waitqueue_head(&dev->buffer_mng_waitq); 358 359 /* alloc common buffer */ 360 dev->common_buffer_size = params->buffer_size * params->num_buffers; 361 dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, 362 &dev->common_buffer_phys, 363 GFP_KERNEL | GFP_DMA); 364 if (!dev->common_buffer) { 365 smscore_unregister_device(dev); 366 return -ENOMEM; 367 } 368 369 /* prepare dma buffers */ 370 for (buffer = dev->common_buffer; 371 dev->num_buffers < params->num_buffers; 372 dev->num_buffers++, buffer += params->buffer_size) { 373 struct smscore_buffer_t *cb = 374 smscore_createbuffer(buffer, dev->common_buffer, 375 dev->common_buffer_phys); 376 if (!cb) { 377 smscore_unregister_device(dev); 378 return -ENOMEM; 379 } 380 381 smscore_putbuffer(dev, cb); 382 } 383 384 sms_info("allocated %d buffers", dev->num_buffers); 385 386 dev->mode = DEVICE_MODE_NONE; 387 dev->context = params->context; 388 dev->device = params->device; 389 dev->setmode_handler = params->setmode_handler; 390 dev->detectmode_handler = params->detectmode_handler; 391 dev->sendrequest_handler = params->sendrequest_handler; 392 dev->preload_handler = params->preload_handler; 393 dev->postload_handler = params->postload_handler; 394 395 dev->device_flags = params->flags; 396 strcpy(dev->devpath, params->devpath); 397 398 smscore_registry_settype(dev->devpath, params->device_type); 399 400 /* add device to devices list */ 401 kmutex_lock(&g_smscore_deviceslock); 402 list_add(&dev->entry, &g_smscore_devices); 403 kmutex_unlock(&g_smscore_deviceslock); 404 405 *coredev = dev; 406 407 sms_info("device %p created", dev); 408 409 return 0; 410 } 411 EXPORT_SYMBOL_GPL(smscore_register_device); 412 413 414 static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev, 415 void *buffer, size_t size, struct completion *completion) { 416 int rc = coredev->sendrequest_handler(coredev->context, buffer, size); 417 if (rc < 0) { 418 sms_info("sendrequest returned error %d", rc); 419 return rc; 420 } 421 422 return wait_for_completion_timeout(completion, 423 msecs_to_jiffies(SMS_PROTOCOL_MAX_RAOUNDTRIP_MS)) ? 424 0 : -ETIME; 425 } 426 427 /** 428 * Starts & enables IR operations 429 * 430 * @return 0 on success, < 0 on error. 431 */ 432 static int smscore_init_ir(struct smscore_device_t *coredev) 433 { 434 int ir_io; 435 int rc; 436 void *buffer; 437 438 coredev->ir.dev = NULL; 439 ir_io = sms_get_board(smscore_get_board_id(coredev))->board_cfg.ir; 440 if (ir_io) {/* only if IR port exist we use IR sub-module */ 441 sms_info("IR loading"); 442 rc = sms_ir_init(coredev); 443 444 if (rc != 0) 445 sms_err("Error initialization DTV IR sub-module"); 446 else { 447 buffer = kmalloc(sizeof(struct SmsMsgData_ST2) + 448 SMS_DMA_ALIGNMENT, 449 GFP_KERNEL | GFP_DMA); 450 if (buffer) { 451 struct SmsMsgData_ST2 *msg = 452 (struct SmsMsgData_ST2 *) 453 SMS_ALIGN_ADDRESS(buffer); 454 455 SMS_INIT_MSG(&msg->xMsgHeader, 456 MSG_SMS_START_IR_REQ, 457 sizeof(struct SmsMsgData_ST2)); 458 msg->msgData[0] = coredev->ir.controller; 459 msg->msgData[1] = coredev->ir.timeout; 460 461 smsendian_handle_tx_message( 462 (struct SmsMsgHdr_ST2 *)msg); 463 rc = smscore_sendrequest_and_wait(coredev, msg, 464 msg->xMsgHeader. msgLength, 465 &coredev->ir_init_done); 466 467 kfree(buffer); 468 } else 469 sms_err 470 ("Sending IR initialization message failed"); 471 } 472 } else 473 sms_info("IR port has not been detected"); 474 475 return 0; 476 } 477 478 /** 479 * sets initial device mode and notifies client hotplugs that device is ready 480 * 481 * @param coredev pointer to a coredev object returned by 482 * smscore_register_device 483 * 484 * @return 0 on success, <0 on error. 485 */ 486 int smscore_start_device(struct smscore_device_t *coredev) 487 { 488 int rc = smscore_set_device_mode( 489 coredev, smscore_registry_getmode(coredev->devpath)); 490 if (rc < 0) { 491 sms_info("set device mode faile , rc %d", rc); 492 return rc; 493 } 494 495 kmutex_lock(&g_smscore_deviceslock); 496 497 rc = smscore_notify_callbacks(coredev, coredev->device, 1); 498 smscore_init_ir(coredev); 499 500 sms_info("device %p started, rc %d", coredev, rc); 501 502 kmutex_unlock(&g_smscore_deviceslock); 503 504 return rc; 505 } 506 EXPORT_SYMBOL_GPL(smscore_start_device); 507 508 509 static int smscore_load_firmware_family2(struct smscore_device_t *coredev, 510 void *buffer, size_t size) 511 { 512 struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer; 513 struct SmsMsgHdr_ST *msg; 514 u32 mem_address; 515 u8 *payload = firmware->Payload; 516 int rc = 0; 517 firmware->StartAddress = le32_to_cpu(firmware->StartAddress); 518 firmware->Length = le32_to_cpu(firmware->Length); 519 520 mem_address = firmware->StartAddress; 521 522 sms_info("loading FW to addr 0x%x size %d", 523 mem_address, firmware->Length); 524 if (coredev->preload_handler) { 525 rc = coredev->preload_handler(coredev->context); 526 if (rc < 0) 527 return rc; 528 } 529 530 /* PAGE_SIZE buffer shall be enough and dma aligned */ 531 msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); 532 if (!msg) 533 return -ENOMEM; 534 535 if (coredev->mode != DEVICE_MODE_NONE) { 536 sms_debug("sending reload command."); 537 SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ, 538 sizeof(struct SmsMsgHdr_ST)); 539 rc = smscore_sendrequest_and_wait(coredev, msg, 540 msg->msgLength, 541 &coredev->reload_start_done); 542 mem_address = *(u32 *) &payload[20]; 543 } 544 545 while (size && rc >= 0) { 546 struct SmsDataDownload_ST *DataMsg = 547 (struct SmsDataDownload_ST *) msg; 548 int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE); 549 550 SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ, 551 (u16)(sizeof(struct SmsMsgHdr_ST) + 552 sizeof(u32) + payload_size)); 553 554 DataMsg->MemAddr = mem_address; 555 memcpy(DataMsg->Payload, payload, payload_size); 556 557 if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) && 558 (coredev->mode == DEVICE_MODE_NONE)) 559 rc = coredev->sendrequest_handler( 560 coredev->context, DataMsg, 561 DataMsg->xMsgHeader.msgLength); 562 else 563 rc = smscore_sendrequest_and_wait( 564 coredev, DataMsg, 565 DataMsg->xMsgHeader.msgLength, 566 &coredev->data_download_done); 567 568 payload += payload_size; 569 size -= payload_size; 570 mem_address += payload_size; 571 } 572 573 if (rc >= 0) { 574 if (coredev->mode == DEVICE_MODE_NONE) { 575 struct SmsMsgData_ST *TriggerMsg = 576 (struct SmsMsgData_ST *) msg; 577 578 SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, 579 sizeof(struct SmsMsgHdr_ST) + 580 sizeof(u32) * 5); 581 582 TriggerMsg->msgData[0] = firmware->StartAddress; 583 /* Entry point */ 584 TriggerMsg->msgData[1] = 5; /* Priority */ 585 TriggerMsg->msgData[2] = 0x200; /* Stack size */ 586 TriggerMsg->msgData[3] = 0; /* Parameter */ 587 TriggerMsg->msgData[4] = 4; /* Task ID */ 588 589 if (coredev->device_flags & SMS_ROM_NO_RESPONSE) { 590 rc = coredev->sendrequest_handler( 591 coredev->context, TriggerMsg, 592 TriggerMsg->xMsgHeader.msgLength); 593 msleep(100); 594 } else 595 rc = smscore_sendrequest_and_wait( 596 coredev, TriggerMsg, 597 TriggerMsg->xMsgHeader.msgLength, 598 &coredev->trigger_done); 599 } else { 600 SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ, 601 sizeof(struct SmsMsgHdr_ST)); 602 603 rc = coredev->sendrequest_handler(coredev->context, 604 msg, msg->msgLength); 605 } 606 msleep(500); 607 } 608 609 sms_debug("rc=%d, postload=%p ", rc, 610 coredev->postload_handler); 611 612 kfree(msg); 613 614 return ((rc >= 0) && coredev->postload_handler) ? 615 coredev->postload_handler(coredev->context) : 616 rc; 617 } 618 619 /** 620 * loads specified firmware into a buffer and calls device loadfirmware_handler 621 * 622 * @param coredev pointer to a coredev object returned by 623 * smscore_register_device 624 * @param filename null-terminated string specifies firmware file name 625 * @param loadfirmware_handler device handler that loads firmware 626 * 627 * @return 0 on success, <0 on error. 628 */ 629 static int smscore_load_firmware_from_file(struct smscore_device_t *coredev, 630 char *filename, 631 loadfirmware_t loadfirmware_handler) 632 { 633 int rc = -ENOENT; 634 const struct firmware *fw; 635 u8 *fw_buffer; 636 637 if (loadfirmware_handler == NULL && !(coredev->device_flags & 638 SMS_DEVICE_FAMILY2)) 639 return -EINVAL; 640 641 rc = request_firmware(&fw, filename, coredev->device); 642 if (rc < 0) { 643 sms_info("failed to open \"%s\"", filename); 644 return rc; 645 } 646 sms_info("read FW %s, size=%zd", filename, fw->size); 647 fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), 648 GFP_KERNEL | GFP_DMA); 649 if (fw_buffer) { 650 memcpy(fw_buffer, fw->data, fw->size); 651 652 rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ? 653 smscore_load_firmware_family2(coredev, 654 fw_buffer, 655 fw->size) : 656 loadfirmware_handler(coredev->context, 657 fw_buffer, fw->size); 658 659 kfree(fw_buffer); 660 } else { 661 sms_info("failed to allocate firmware buffer"); 662 rc = -ENOMEM; 663 } 664 665 release_firmware(fw); 666 667 return rc; 668 } 669 670 /** 671 * notifies all clients registered with the device, notifies hotplugs, 672 * frees all buffers and coredev object 673 * 674 * @param coredev pointer to a coredev object returned by 675 * smscore_register_device 676 * 677 * @return 0 on success, <0 on error. 678 */ 679 void smscore_unregister_device(struct smscore_device_t *coredev) 680 { 681 struct smscore_buffer_t *cb; 682 int num_buffers = 0; 683 int retry = 0; 684 685 kmutex_lock(&g_smscore_deviceslock); 686 687 /* Release input device (IR) resources */ 688 sms_ir_exit(coredev); 689 690 smscore_notify_clients(coredev); 691 smscore_notify_callbacks(coredev, NULL, 0); 692 693 /* at this point all buffers should be back 694 * onresponse must no longer be called */ 695 696 while (1) { 697 while (!list_empty(&coredev->buffers)) { 698 cb = (struct smscore_buffer_t *) coredev->buffers.next; 699 list_del(&cb->entry); 700 kfree(cb); 701 num_buffers++; 702 } 703 if (num_buffers == coredev->num_buffers) 704 break; 705 if (++retry > 10) { 706 sms_info("exiting although " 707 "not all buffers released."); 708 break; 709 } 710 711 sms_info("waiting for %d buffer(s)", 712 coredev->num_buffers - num_buffers); 713 msleep(100); 714 } 715 716 sms_info("freed %d buffers", num_buffers); 717 718 if (coredev->common_buffer) 719 dma_free_coherent(NULL, coredev->common_buffer_size, 720 coredev->common_buffer, coredev->common_buffer_phys); 721 722 if (coredev->fw_buf != NULL) 723 kfree(coredev->fw_buf); 724 725 list_del(&coredev->entry); 726 kfree(coredev); 727 728 kmutex_unlock(&g_smscore_deviceslock); 729 730 sms_info("device %p destroyed", coredev); 731 } 732 EXPORT_SYMBOL_GPL(smscore_unregister_device); 733 734 static int smscore_detect_mode(struct smscore_device_t *coredev) 735 { 736 void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT, 737 GFP_KERNEL | GFP_DMA); 738 struct SmsMsgHdr_ST *msg = 739 (struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer); 740 int rc; 741 742 if (!buffer) 743 return -ENOMEM; 744 745 SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ, 746 sizeof(struct SmsMsgHdr_ST)); 747 748 rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, 749 &coredev->version_ex_done); 750 if (rc == -ETIME) { 751 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try"); 752 753 if (wait_for_completion_timeout(&coredev->resume_done, 754 msecs_to_jiffies(5000))) { 755 rc = smscore_sendrequest_and_wait( 756 coredev, msg, msg->msgLength, 757 &coredev->version_ex_done); 758 if (rc < 0) 759 sms_err("MSG_SMS_GET_VERSION_EX_REQ failed " 760 "second try, rc %d", rc); 761 } else 762 rc = -ETIME; 763 } 764 765 kfree(buffer); 766 767 return rc; 768 } 769 770 static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = { 771 /*Stellar NOVA A0 Nova B0 VEGA*/ 772 /*DVBT*/ 773 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, 774 /*DVBH*/ 775 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, 776 /*TDMB*/ 777 {"none", "tdmb_nova_12mhz.inp", "tdmb_nova_12mhz_b0.inp", "none"}, 778 /*DABIP*/ 779 {"none", "none", "none", "none"}, 780 /*BDA*/ 781 {"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"}, 782 /*ISDBT*/ 783 {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, 784 /*ISDBTBDA*/ 785 {"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"}, 786 /*CMMB*/ 787 {"none", "none", "none", "cmmb_vega_12mhz.inp"} 788 }; 789 790 static inline char *sms_get_fw_name(struct smscore_device_t *coredev, 791 int mode, enum sms_device_type_st type) 792 { 793 char **fw = sms_get_board(smscore_get_board_id(coredev))->fw; 794 return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type]; 795 } 796 797 /** 798 * calls device handler to change mode of operation 799 * NOTE: stellar/usb may disconnect when changing mode 800 * 801 * @param coredev pointer to a coredev object returned by 802 * smscore_register_device 803 * @param mode requested mode of operation 804 * 805 * @return 0 on success, <0 on error. 806 */ 807 int smscore_set_device_mode(struct smscore_device_t *coredev, int mode) 808 { 809 void *buffer; 810 int rc = 0; 811 enum sms_device_type_st type; 812 813 sms_debug("set device mode to %d", mode); 814 if (coredev->device_flags & SMS_DEVICE_FAMILY2) { 815 if (mode < DEVICE_MODE_DVBT || mode >= DEVICE_MODE_RAW_TUNER) { 816 sms_err("invalid mode specified %d", mode); 817 return -EINVAL; 818 } 819 820 smscore_registry_setmode(coredev->devpath, mode); 821 822 if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) { 823 rc = smscore_detect_mode(coredev); 824 if (rc < 0) { 825 sms_err("mode detect failed %d", rc); 826 return rc; 827 } 828 } 829 830 if (coredev->mode == mode) { 831 sms_info("device mode %d already set", mode); 832 return 0; 833 } 834 835 if (!(coredev->modes_supported & (1 << mode))) { 836 char *fw_filename; 837 838 type = smscore_registry_gettype(coredev->devpath); 839 fw_filename = sms_get_fw_name(coredev, mode, type); 840 841 rc = smscore_load_firmware_from_file(coredev, 842 fw_filename, NULL); 843 if (rc < 0) { 844 sms_warn("error %d loading firmware: %s, " 845 "trying again with default firmware", 846 rc, fw_filename); 847 848 /* try again with the default firmware */ 849 fw_filename = smscore_fw_lkup[mode][type]; 850 rc = smscore_load_firmware_from_file(coredev, 851 fw_filename, NULL); 852 853 if (rc < 0) { 854 sms_warn("error %d loading " 855 "firmware: %s", rc, 856 fw_filename); 857 return rc; 858 } 859 } 860 sms_log("firmware download success: %s", fw_filename); 861 } else 862 sms_info("mode %d supported by running " 863 "firmware", mode); 864 865 buffer = kmalloc(sizeof(struct SmsMsgData_ST) + 866 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA); 867 if (buffer) { 868 struct SmsMsgData_ST *msg = 869 (struct SmsMsgData_ST *) 870 SMS_ALIGN_ADDRESS(buffer); 871 872 SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, 873 sizeof(struct SmsMsgData_ST)); 874 msg->msgData[0] = mode; 875 876 rc = smscore_sendrequest_and_wait( 877 coredev, msg, msg->xMsgHeader.msgLength, 878 &coredev->init_device_done); 879 880 kfree(buffer); 881 } else { 882 sms_err("Could not allocate buffer for " 883 "init device message."); 884 rc = -ENOMEM; 885 } 886 } else { 887 if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) { 888 sms_err("invalid mode specified %d", mode); 889 return -EINVAL; 890 } 891 892 smscore_registry_setmode(coredev->devpath, mode); 893 894 if (coredev->detectmode_handler) 895 coredev->detectmode_handler(coredev->context, 896 &coredev->mode); 897 898 if (coredev->mode != mode && coredev->setmode_handler) 899 rc = coredev->setmode_handler(coredev->context, mode); 900 } 901 902 if (rc >= 0) { 903 coredev->mode = mode; 904 coredev->device_flags &= ~SMS_DEVICE_NOT_READY; 905 } 906 907 if (rc < 0) 908 sms_err("return error code %d.", rc); 909 return rc; 910 } 911 912 /** 913 * calls device handler to get current mode of operation 914 * 915 * @param coredev pointer to a coredev object returned by 916 * smscore_register_device 917 * 918 * @return current mode 919 */ 920 int smscore_get_device_mode(struct smscore_device_t *coredev) 921 { 922 return coredev->mode; 923 } 924 EXPORT_SYMBOL_GPL(smscore_get_device_mode); 925 926 /** 927 * find client by response id & type within the clients list. 928 * return client handle or NULL. 929 * 930 * @param coredev pointer to a coredev object returned by 931 * smscore_register_device 932 * @param data_type client data type (SMS_DONT_CARE for all types) 933 * @param id client id (SMS_DONT_CARE for all id) 934 * 935 */ 936 static struct 937 smscore_client_t *smscore_find_client(struct smscore_device_t *coredev, 938 int data_type, int id) 939 { 940 struct list_head *first; 941 struct smscore_client_t *client; 942 unsigned long flags; 943 struct list_head *firstid; 944 struct smscore_idlist_t *client_id; 945 946 spin_lock_irqsave(&coredev->clientslock, flags); 947 first = &coredev->clients; 948 list_for_each_entry(client, first, entry) { 949 firstid = &client->idlist; 950 list_for_each_entry(client_id, firstid, entry) { 951 if ((client_id->id == id) && 952 (client_id->data_type == data_type || 953 (client_id->data_type == 0))) 954 goto found; 955 } 956 } 957 client = NULL; 958 found: 959 spin_unlock_irqrestore(&coredev->clientslock, flags); 960 return client; 961 } 962 963 /** 964 * find client by response id/type, call clients onresponse handler 965 * return buffer to pool on error 966 * 967 * @param coredev pointer to a coredev object returned by 968 * smscore_register_device 969 * @param cb pointer to response buffer descriptor 970 * 971 */ 972 void smscore_onresponse(struct smscore_device_t *coredev, 973 struct smscore_buffer_t *cb) { 974 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) ((u8 *) cb->p 975 + cb->offset); 976 struct smscore_client_t *client; 977 int rc = -EBUSY; 978 static unsigned long last_sample_time; /* = 0; */ 979 static int data_total; /* = 0; */ 980 unsigned long time_now = jiffies_to_msecs(jiffies); 981 982 if (!last_sample_time) 983 last_sample_time = time_now; 984 985 if (time_now - last_sample_time > 10000) { 986 sms_debug("\ndata rate %d bytes/secs", 987 (int)((data_total * 1000) / 988 (time_now - last_sample_time))); 989 990 last_sample_time = time_now; 991 data_total = 0; 992 } 993 994 data_total += cb->size; 995 /* Do we need to re-route? */ 996 if ((phdr->msgType == MSG_SMS_HO_PER_SLICES_IND) || 997 (phdr->msgType == MSG_SMS_TRANSMISSION_IND)) { 998 if (coredev->mode == DEVICE_MODE_DVBT_BDA) 999 phdr->msgDstId = DVBT_BDA_CONTROL_MSG_ID; 1000 } 1001 1002 1003 client = smscore_find_client(coredev, phdr->msgType, phdr->msgDstId); 1004 1005 /* If no client registered for type & id, 1006 * check for control client where type is not registered */ 1007 if (client) 1008 rc = client->onresponse_handler(client->context, cb); 1009 1010 if (rc < 0) { 1011 switch (phdr->msgType) { 1012 case MSG_SMS_GET_VERSION_EX_RES: 1013 { 1014 struct SmsVersionRes_ST *ver = 1015 (struct SmsVersionRes_ST *) phdr; 1016 sms_debug("MSG_SMS_GET_VERSION_EX_RES " 1017 "id %d prots 0x%x ver %d.%d", 1018 ver->FirmwareId, ver->SupportedProtocols, 1019 ver->RomVersionMajor, ver->RomVersionMinor); 1020 1021 coredev->mode = ver->FirmwareId == 255 ? 1022 DEVICE_MODE_NONE : ver->FirmwareId; 1023 coredev->modes_supported = ver->SupportedProtocols; 1024 1025 complete(&coredev->version_ex_done); 1026 break; 1027 } 1028 case MSG_SMS_INIT_DEVICE_RES: 1029 sms_debug("MSG_SMS_INIT_DEVICE_RES"); 1030 complete(&coredev->init_device_done); 1031 break; 1032 case MSG_SW_RELOAD_START_RES: 1033 sms_debug("MSG_SW_RELOAD_START_RES"); 1034 complete(&coredev->reload_start_done); 1035 break; 1036 case MSG_SMS_DATA_DOWNLOAD_RES: 1037 complete(&coredev->data_download_done); 1038 break; 1039 case MSG_SW_RELOAD_EXEC_RES: 1040 sms_debug("MSG_SW_RELOAD_EXEC_RES"); 1041 break; 1042 case MSG_SMS_SWDOWNLOAD_TRIGGER_RES: 1043 sms_debug("MSG_SMS_SWDOWNLOAD_TRIGGER_RES"); 1044 complete(&coredev->trigger_done); 1045 break; 1046 case MSG_SMS_SLEEP_RESUME_COMP_IND: 1047 complete(&coredev->resume_done); 1048 break; 1049 case MSG_SMS_GPIO_CONFIG_EX_RES: 1050 sms_debug("MSG_SMS_GPIO_CONFIG_EX_RES"); 1051 complete(&coredev->gpio_configuration_done); 1052 break; 1053 case MSG_SMS_GPIO_SET_LEVEL_RES: 1054 sms_debug("MSG_SMS_GPIO_SET_LEVEL_RES"); 1055 complete(&coredev->gpio_set_level_done); 1056 break; 1057 case MSG_SMS_GPIO_GET_LEVEL_RES: 1058 { 1059 u32 *msgdata = (u32 *) phdr; 1060 coredev->gpio_get_res = msgdata[1]; 1061 sms_debug("MSG_SMS_GPIO_GET_LEVEL_RES gpio level %d", 1062 coredev->gpio_get_res); 1063 complete(&coredev->gpio_get_level_done); 1064 break; 1065 } 1066 case MSG_SMS_START_IR_RES: 1067 complete(&coredev->ir_init_done); 1068 break; 1069 case MSG_SMS_IR_SAMPLES_IND: 1070 sms_ir_event(coredev, 1071 (const char *) 1072 ((char *)phdr 1073 + sizeof(struct SmsMsgHdr_ST)), 1074 (int)phdr->msgLength 1075 - sizeof(struct SmsMsgHdr_ST)); 1076 break; 1077 1078 default: 1079 break; 1080 } 1081 smscore_putbuffer(coredev, cb); 1082 } 1083 } 1084 EXPORT_SYMBOL_GPL(smscore_onresponse); 1085 1086 /** 1087 * return pointer to next free buffer descriptor from core pool 1088 * 1089 * @param coredev pointer to a coredev object returned by 1090 * smscore_register_device 1091 * 1092 * @return pointer to descriptor on success, NULL on error. 1093 */ 1094 1095 struct smscore_buffer_t *get_entry(struct smscore_device_t *coredev) 1096 { 1097 struct smscore_buffer_t *cb = NULL; 1098 unsigned long flags; 1099 1100 spin_lock_irqsave(&coredev->bufferslock, flags); 1101 if (!list_empty(&coredev->buffers)) { 1102 cb = (struct smscore_buffer_t *) coredev->buffers.next; 1103 list_del(&cb->entry); 1104 } 1105 spin_unlock_irqrestore(&coredev->bufferslock, flags); 1106 return cb; 1107 } 1108 1109 struct smscore_buffer_t *smscore_getbuffer(struct smscore_device_t *coredev) 1110 { 1111 struct smscore_buffer_t *cb = NULL; 1112 1113 wait_event(coredev->buffer_mng_waitq, (cb = get_entry(coredev))); 1114 1115 return cb; 1116 } 1117 EXPORT_SYMBOL_GPL(smscore_getbuffer); 1118 1119 /** 1120 * return buffer descriptor to a pool 1121 * 1122 * @param coredev pointer to a coredev object returned by 1123 * smscore_register_device 1124 * @param cb pointer buffer descriptor 1125 * 1126 */ 1127 void smscore_putbuffer(struct smscore_device_t *coredev, 1128 struct smscore_buffer_t *cb) { 1129 wake_up_interruptible(&coredev->buffer_mng_waitq); 1130 list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock); 1131 } 1132 EXPORT_SYMBOL_GPL(smscore_putbuffer); 1133 1134 static int smscore_validate_client(struct smscore_device_t *coredev, 1135 struct smscore_client_t *client, 1136 int data_type, int id) 1137 { 1138 struct smscore_idlist_t *listentry; 1139 struct smscore_client_t *registered_client; 1140 1141 if (!client) { 1142 sms_err("bad parameter."); 1143 return -EINVAL; 1144 } 1145 registered_client = smscore_find_client(coredev, data_type, id); 1146 if (registered_client == client) 1147 return 0; 1148 1149 if (registered_client) { 1150 sms_err("The msg ID already registered to another client."); 1151 return -EEXIST; 1152 } 1153 listentry = kzalloc(sizeof(struct smscore_idlist_t), GFP_KERNEL); 1154 if (!listentry) { 1155 sms_err("Can't allocate memory for client id."); 1156 return -ENOMEM; 1157 } 1158 listentry->id = id; 1159 listentry->data_type = data_type; 1160 list_add_locked(&listentry->entry, &client->idlist, 1161 &coredev->clientslock); 1162 return 0; 1163 } 1164 1165 /** 1166 * creates smsclient object, check that id is taken by another client 1167 * 1168 * @param coredev pointer to a coredev object from clients hotplug 1169 * @param initial_id all messages with this id would be sent to this client 1170 * @param data_type all messages of this type would be sent to this client 1171 * @param onresponse_handler client handler that is called to 1172 * process incoming messages 1173 * @param onremove_handler client handler that is called when device is removed 1174 * @param context client-specific context 1175 * @param client pointer to a value that receives created smsclient object 1176 * 1177 * @return 0 on success, <0 on error. 1178 */ 1179 int smscore_register_client(struct smscore_device_t *coredev, 1180 struct smsclient_params_t *params, 1181 struct smscore_client_t **client) 1182 { 1183 struct smscore_client_t *newclient; 1184 /* check that no other channel with same parameters exists */ 1185 if (smscore_find_client(coredev, params->data_type, 1186 params->initial_id)) { 1187 sms_err("Client already exist."); 1188 return -EEXIST; 1189 } 1190 1191 newclient = kzalloc(sizeof(struct smscore_client_t), GFP_KERNEL); 1192 if (!newclient) { 1193 sms_err("Failed to allocate memory for client."); 1194 return -ENOMEM; 1195 } 1196 1197 INIT_LIST_HEAD(&newclient->idlist); 1198 newclient->coredev = coredev; 1199 newclient->onresponse_handler = params->onresponse_handler; 1200 newclient->onremove_handler = params->onremove_handler; 1201 newclient->context = params->context; 1202 list_add_locked(&newclient->entry, &coredev->clients, 1203 &coredev->clientslock); 1204 smscore_validate_client(coredev, newclient, params->data_type, 1205 params->initial_id); 1206 *client = newclient; 1207 sms_debug("%p %d %d", params->context, params->data_type, 1208 params->initial_id); 1209 1210 return 0; 1211 } 1212 EXPORT_SYMBOL_GPL(smscore_register_client); 1213 1214 /** 1215 * frees smsclient object and all subclients associated with it 1216 * 1217 * @param client pointer to smsclient object returned by 1218 * smscore_register_client 1219 * 1220 */ 1221 void smscore_unregister_client(struct smscore_client_t *client) 1222 { 1223 struct smscore_device_t *coredev = client->coredev; 1224 unsigned long flags; 1225 1226 spin_lock_irqsave(&coredev->clientslock, flags); 1227 1228 1229 while (!list_empty(&client->idlist)) { 1230 struct smscore_idlist_t *identry = 1231 (struct smscore_idlist_t *) client->idlist.next; 1232 list_del(&identry->entry); 1233 kfree(identry); 1234 } 1235 1236 sms_info("%p", client->context); 1237 1238 list_del(&client->entry); 1239 kfree(client); 1240 1241 spin_unlock_irqrestore(&coredev->clientslock, flags); 1242 } 1243 EXPORT_SYMBOL_GPL(smscore_unregister_client); 1244 1245 /** 1246 * verifies that source id is not taken by another client, 1247 * calls device handler to send requests to the device 1248 * 1249 * @param client pointer to smsclient object returned by 1250 * smscore_register_client 1251 * @param buffer pointer to a request buffer 1252 * @param size size (in bytes) of request buffer 1253 * 1254 * @return 0 on success, <0 on error. 1255 */ 1256 int smsclient_sendrequest(struct smscore_client_t *client, 1257 void *buffer, size_t size) 1258 { 1259 struct smscore_device_t *coredev; 1260 struct SmsMsgHdr_ST *phdr = (struct SmsMsgHdr_ST *) buffer; 1261 int rc; 1262 1263 if (client == NULL) { 1264 sms_err("Got NULL client"); 1265 return -EINVAL; 1266 } 1267 1268 coredev = client->coredev; 1269 1270 /* check that no other channel with same id exists */ 1271 if (coredev == NULL) { 1272 sms_err("Got NULL coredev"); 1273 return -EINVAL; 1274 } 1275 1276 rc = smscore_validate_client(client->coredev, client, 0, 1277 phdr->msgSrcId); 1278 if (rc < 0) 1279 return rc; 1280 1281 return coredev->sendrequest_handler(coredev->context, buffer, size); 1282 } 1283 EXPORT_SYMBOL_GPL(smsclient_sendrequest); 1284 1285 1286 /* old GPIO managements implementation */ 1287 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin, 1288 struct smscore_config_gpio *pinconfig) 1289 { 1290 struct { 1291 struct SmsMsgHdr_ST hdr; 1292 u32 data[6]; 1293 } msg; 1294 1295 if (coredev->device_flags & SMS_DEVICE_FAMILY2) { 1296 msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; 1297 msg.hdr.msgDstId = HIF_TASK; 1298 msg.hdr.msgFlags = 0; 1299 msg.hdr.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; 1300 msg.hdr.msgLength = sizeof(msg); 1301 1302 msg.data[0] = pin; 1303 msg.data[1] = pinconfig->pullupdown; 1304 1305 /* Convert slew rate for Nova: Fast(0) = 3 / Slow(1) = 0; */ 1306 msg.data[2] = pinconfig->outputslewrate == 0 ? 3 : 0; 1307 1308 switch (pinconfig->outputdriving) { 1309 case SMS_GPIO_OUTPUTDRIVING_16mA: 1310 msg.data[3] = 7; /* Nova - 16mA */ 1311 break; 1312 case SMS_GPIO_OUTPUTDRIVING_12mA: 1313 msg.data[3] = 5; /* Nova - 11mA */ 1314 break; 1315 case SMS_GPIO_OUTPUTDRIVING_8mA: 1316 msg.data[3] = 3; /* Nova - 7mA */ 1317 break; 1318 case SMS_GPIO_OUTPUTDRIVING_4mA: 1319 default: 1320 msg.data[3] = 2; /* Nova - 4mA */ 1321 break; 1322 } 1323 1324 msg.data[4] = pinconfig->direction; 1325 msg.data[5] = 0; 1326 } else /* TODO: SMS_DEVICE_FAMILY1 */ 1327 return -EINVAL; 1328 1329 return coredev->sendrequest_handler(coredev->context, 1330 &msg, sizeof(msg)); 1331 } 1332 1333 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level) 1334 { 1335 struct { 1336 struct SmsMsgHdr_ST hdr; 1337 u32 data[3]; 1338 } msg; 1339 1340 if (pin > MAX_GPIO_PIN_NUMBER) 1341 return -EINVAL; 1342 1343 msg.hdr.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; 1344 msg.hdr.msgDstId = HIF_TASK; 1345 msg.hdr.msgFlags = 0; 1346 msg.hdr.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; 1347 msg.hdr.msgLength = sizeof(msg); 1348 1349 msg.data[0] = pin; 1350 msg.data[1] = level ? 1 : 0; 1351 msg.data[2] = 0; 1352 1353 return coredev->sendrequest_handler(coredev->context, 1354 &msg, sizeof(msg)); 1355 } 1356 1357 /* new GPIO management implementation */ 1358 static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum, 1359 u32 *pGroupNum, u32 *pGroupCfg) { 1360 1361 *pGroupCfg = 1; 1362 1363 if (PinNum <= 1) { 1364 *pTranslatedPinNum = 0; 1365 *pGroupNum = 9; 1366 *pGroupCfg = 2; 1367 } else if (PinNum >= 2 && PinNum <= 6) { 1368 *pTranslatedPinNum = 2; 1369 *pGroupNum = 0; 1370 *pGroupCfg = 2; 1371 } else if (PinNum >= 7 && PinNum <= 11) { 1372 *pTranslatedPinNum = 7; 1373 *pGroupNum = 1; 1374 } else if (PinNum >= 12 && PinNum <= 15) { 1375 *pTranslatedPinNum = 12; 1376 *pGroupNum = 2; 1377 *pGroupCfg = 3; 1378 } else if (PinNum == 16) { 1379 *pTranslatedPinNum = 16; 1380 *pGroupNum = 23; 1381 } else if (PinNum >= 17 && PinNum <= 24) { 1382 *pTranslatedPinNum = 17; 1383 *pGroupNum = 3; 1384 } else if (PinNum == 25) { 1385 *pTranslatedPinNum = 25; 1386 *pGroupNum = 6; 1387 } else if (PinNum >= 26 && PinNum <= 28) { 1388 *pTranslatedPinNum = 26; 1389 *pGroupNum = 4; 1390 } else if (PinNum == 29) { 1391 *pTranslatedPinNum = 29; 1392 *pGroupNum = 5; 1393 *pGroupCfg = 2; 1394 } else if (PinNum == 30) { 1395 *pTranslatedPinNum = 30; 1396 *pGroupNum = 8; 1397 } else if (PinNum == 31) { 1398 *pTranslatedPinNum = 31; 1399 *pGroupNum = 17; 1400 } else 1401 return -1; 1402 1403 *pGroupCfg <<= 24; 1404 1405 return 0; 1406 } 1407 1408 int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum, 1409 struct smscore_gpio_config *pGpioConfig) { 1410 1411 u32 totalLen; 1412 u32 TranslatedPinNum = 0; 1413 u32 GroupNum = 0; 1414 u32 ElectricChar; 1415 u32 groupCfg; 1416 void *buffer; 1417 int rc; 1418 1419 struct SetGpioMsg { 1420 struct SmsMsgHdr_ST xMsgHeader; 1421 u32 msgData[6]; 1422 } *pMsg; 1423 1424 1425 if (PinNum > MAX_GPIO_PIN_NUMBER) 1426 return -EINVAL; 1427 1428 if (pGpioConfig == NULL) 1429 return -EINVAL; 1430 1431 totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6); 1432 1433 buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, 1434 GFP_KERNEL | GFP_DMA); 1435 if (!buffer) 1436 return -ENOMEM; 1437 1438 pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); 1439 1440 pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; 1441 pMsg->xMsgHeader.msgDstId = HIF_TASK; 1442 pMsg->xMsgHeader.msgFlags = 0; 1443 pMsg->xMsgHeader.msgLength = (u16) totalLen; 1444 pMsg->msgData[0] = PinNum; 1445 1446 if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) { 1447 pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ; 1448 if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum, 1449 &groupCfg) != 0) { 1450 rc = -EINVAL; 1451 goto free; 1452 } 1453 1454 pMsg->msgData[1] = TranslatedPinNum; 1455 pMsg->msgData[2] = GroupNum; 1456 ElectricChar = (pGpioConfig->PullUpDown) 1457 | (pGpioConfig->InputCharacteristics << 2) 1458 | (pGpioConfig->OutputSlewRate << 3) 1459 | (pGpioConfig->OutputDriving << 4); 1460 pMsg->msgData[3] = ElectricChar; 1461 pMsg->msgData[4] = pGpioConfig->Direction; 1462 pMsg->msgData[5] = groupCfg; 1463 } else { 1464 pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ; 1465 pMsg->msgData[1] = pGpioConfig->PullUpDown; 1466 pMsg->msgData[2] = pGpioConfig->OutputSlewRate; 1467 pMsg->msgData[3] = pGpioConfig->OutputDriving; 1468 pMsg->msgData[4] = pGpioConfig->Direction; 1469 pMsg->msgData[5] = 0; 1470 } 1471 1472 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); 1473 rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, 1474 &coredev->gpio_configuration_done); 1475 1476 if (rc != 0) { 1477 if (rc == -ETIME) 1478 sms_err("smscore_gpio_configure timeout"); 1479 else 1480 sms_err("smscore_gpio_configure error"); 1481 } 1482 free: 1483 kfree(buffer); 1484 1485 return rc; 1486 } 1487 1488 int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum, 1489 u8 NewLevel) { 1490 1491 u32 totalLen; 1492 int rc; 1493 void *buffer; 1494 1495 struct SetGpioMsg { 1496 struct SmsMsgHdr_ST xMsgHeader; 1497 u32 msgData[3]; /* keep it 3 ! */ 1498 } *pMsg; 1499 1500 if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER)) 1501 return -EINVAL; 1502 1503 totalLen = sizeof(struct SmsMsgHdr_ST) + 1504 (3 * sizeof(u32)); /* keep it 3 ! */ 1505 1506 buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, 1507 GFP_KERNEL | GFP_DMA); 1508 if (!buffer) 1509 return -ENOMEM; 1510 1511 pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); 1512 1513 pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; 1514 pMsg->xMsgHeader.msgDstId = HIF_TASK; 1515 pMsg->xMsgHeader.msgFlags = 0; 1516 pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ; 1517 pMsg->xMsgHeader.msgLength = (u16) totalLen; 1518 pMsg->msgData[0] = PinNum; 1519 pMsg->msgData[1] = NewLevel; 1520 1521 /* Send message to SMS */ 1522 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); 1523 rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, 1524 &coredev->gpio_set_level_done); 1525 1526 if (rc != 0) { 1527 if (rc == -ETIME) 1528 sms_err("smscore_gpio_set_level timeout"); 1529 else 1530 sms_err("smscore_gpio_set_level error"); 1531 } 1532 kfree(buffer); 1533 1534 return rc; 1535 } 1536 1537 int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum, 1538 u8 *level) { 1539 1540 u32 totalLen; 1541 int rc; 1542 void *buffer; 1543 1544 struct SetGpioMsg { 1545 struct SmsMsgHdr_ST xMsgHeader; 1546 u32 msgData[2]; 1547 } *pMsg; 1548 1549 1550 if (PinNum > MAX_GPIO_PIN_NUMBER) 1551 return -EINVAL; 1552 1553 totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32)); 1554 1555 buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT, 1556 GFP_KERNEL | GFP_DMA); 1557 if (!buffer) 1558 return -ENOMEM; 1559 1560 pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer); 1561 1562 pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID; 1563 pMsg->xMsgHeader.msgDstId = HIF_TASK; 1564 pMsg->xMsgHeader.msgFlags = 0; 1565 pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ; 1566 pMsg->xMsgHeader.msgLength = (u16) totalLen; 1567 pMsg->msgData[0] = PinNum; 1568 pMsg->msgData[1] = 0; 1569 1570 /* Send message to SMS */ 1571 smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg); 1572 rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen, 1573 &coredev->gpio_get_level_done); 1574 1575 if (rc != 0) { 1576 if (rc == -ETIME) 1577 sms_err("smscore_gpio_get_level timeout"); 1578 else 1579 sms_err("smscore_gpio_get_level error"); 1580 } 1581 kfree(buffer); 1582 1583 /* Its a race between other gpio_get_level() and the copy of the single 1584 * global 'coredev->gpio_get_res' to the function's variable 'level' 1585 */ 1586 *level = coredev->gpio_get_res; 1587 1588 return rc; 1589 } 1590 1591 static int __init smscore_module_init(void) 1592 { 1593 int rc = 0; 1594 1595 INIT_LIST_HEAD(&g_smscore_notifyees); 1596 INIT_LIST_HEAD(&g_smscore_devices); 1597 kmutex_init(&g_smscore_deviceslock); 1598 1599 INIT_LIST_HEAD(&g_smscore_registry); 1600 kmutex_init(&g_smscore_registrylock); 1601 1602 return rc; 1603 } 1604 1605 static void __exit smscore_module_exit(void) 1606 { 1607 kmutex_lock(&g_smscore_deviceslock); 1608 while (!list_empty(&g_smscore_notifyees)) { 1609 struct smscore_device_notifyee_t *notifyee = 1610 (struct smscore_device_notifyee_t *) 1611 g_smscore_notifyees.next; 1612 1613 list_del(¬ifyee->entry); 1614 kfree(notifyee); 1615 } 1616 kmutex_unlock(&g_smscore_deviceslock); 1617 1618 kmutex_lock(&g_smscore_registrylock); 1619 while (!list_empty(&g_smscore_registry)) { 1620 struct smscore_registry_entry_t *entry = 1621 (struct smscore_registry_entry_t *) 1622 g_smscore_registry.next; 1623 1624 list_del(&entry->entry); 1625 kfree(entry); 1626 } 1627 kmutex_unlock(&g_smscore_registrylock); 1628 1629 sms_debug(""); 1630 } 1631 1632 module_init(smscore_module_init); 1633 module_exit(smscore_module_exit); 1634 1635 MODULE_DESCRIPTION("Siano MDTV Core module"); 1636 MODULE_AUTHOR("Siano Mobile Silicon, Inc. (uris@siano-ms.com)"); 1637 MODULE_LICENSE("GPL"); 1638