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