1 /* 2 * H/W layer of ISHTP provider device (ISH) 3 * 4 * Copyright (c) 2014-2016, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 */ 15 16 #include <linux/sched.h> 17 #include <linux/spinlock.h> 18 #include <linux/delay.h> 19 #include <linux/jiffies.h> 20 #include "client.h" 21 #include "hw-ish.h" 22 #include "hbm.h" 23 24 /* For FW reset flow */ 25 static struct work_struct fw_reset_work; 26 static struct ishtp_device *ishtp_dev; 27 28 /** 29 * ish_reg_read() - Read register 30 * @dev: ISHTP device pointer 31 * @offset: Register offset 32 * 33 * Read 32 bit register at a given offset 34 * 35 * Return: Read register value 36 */ 37 static inline uint32_t ish_reg_read(const struct ishtp_device *dev, 38 unsigned long offset) 39 { 40 struct ish_hw *hw = to_ish_hw(dev); 41 42 return readl(hw->mem_addr + offset); 43 } 44 45 /** 46 * ish_reg_write() - Write register 47 * @dev: ISHTP device pointer 48 * @offset: Register offset 49 * @value: Value to write 50 * 51 * Writes 32 bit register at a give offset 52 */ 53 static inline void ish_reg_write(struct ishtp_device *dev, 54 unsigned long offset, 55 uint32_t value) 56 { 57 struct ish_hw *hw = to_ish_hw(dev); 58 59 writel(value, hw->mem_addr + offset); 60 } 61 62 /** 63 * _ish_read_fw_sts_reg() - Read FW status register 64 * @dev: ISHTP device pointer 65 * 66 * Read FW status register 67 * 68 * Return: Read register value 69 */ 70 static inline uint32_t _ish_read_fw_sts_reg(struct ishtp_device *dev) 71 { 72 return ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 73 } 74 75 /** 76 * check_generated_interrupt() - Check if ISH interrupt 77 * @dev: ISHTP device pointer 78 * 79 * Check if an interrupt was generated for ISH 80 * 81 * Return: Read true or false 82 */ 83 static bool check_generated_interrupt(struct ishtp_device *dev) 84 { 85 bool interrupt_generated = true; 86 uint32_t pisr_val = 0; 87 88 if (dev->pdev->device == CHV_DEVICE_ID) { 89 pisr_val = ish_reg_read(dev, IPC_REG_PISR_CHV_AB); 90 interrupt_generated = 91 IPC_INT_FROM_ISH_TO_HOST_CHV_AB(pisr_val); 92 } else { 93 pisr_val = ish_reg_read(dev, IPC_REG_PISR_BXT); 94 interrupt_generated = IPC_INT_FROM_ISH_TO_HOST_BXT(pisr_val); 95 } 96 97 return interrupt_generated; 98 } 99 100 /** 101 * ish_is_input_ready() - Check if FW ready for RX 102 * @dev: ISHTP device pointer 103 * 104 * Check if ISH FW is ready for receiving data 105 * 106 * Return: Read true or false 107 */ 108 static bool ish_is_input_ready(struct ishtp_device *dev) 109 { 110 uint32_t doorbell_val; 111 112 doorbell_val = ish_reg_read(dev, IPC_REG_HOST2ISH_DRBL); 113 return !IPC_IS_BUSY(doorbell_val); 114 } 115 116 /** 117 * set_host_ready() - Indicate host ready 118 * @dev: ISHTP device pointer 119 * 120 * Set host ready indication to FW 121 */ 122 static void set_host_ready(struct ishtp_device *dev) 123 { 124 if (dev->pdev->device == CHV_DEVICE_ID) { 125 if (dev->pdev->revision == REVISION_ID_CHT_A0 || 126 (dev->pdev->revision & REVISION_ID_SI_MASK) == 127 REVISION_ID_CHT_Ax_SI) 128 ish_reg_write(dev, IPC_REG_HOST_COMM, 0x81); 129 else if (dev->pdev->revision == REVISION_ID_CHT_B0 || 130 (dev->pdev->revision & REVISION_ID_SI_MASK) == 131 REVISION_ID_CHT_Bx_SI || 132 (dev->pdev->revision & REVISION_ID_SI_MASK) == 133 REVISION_ID_CHT_Kx_SI || 134 (dev->pdev->revision & REVISION_ID_SI_MASK) == 135 REVISION_ID_CHT_Dx_SI) { 136 uint32_t host_comm_val; 137 138 host_comm_val = ish_reg_read(dev, IPC_REG_HOST_COMM); 139 host_comm_val |= IPC_HOSTCOMM_INT_EN_BIT_CHV_AB | 0x81; 140 ish_reg_write(dev, IPC_REG_HOST_COMM, host_comm_val); 141 } 142 } else { 143 uint32_t host_pimr_val; 144 145 host_pimr_val = ish_reg_read(dev, IPC_REG_PIMR_BXT); 146 host_pimr_val |= IPC_PIMR_INT_EN_BIT_BXT; 147 /* 148 * disable interrupt generated instead of 149 * RX_complete_msg 150 */ 151 host_pimr_val &= ~IPC_HOST2ISH_BUSYCLEAR_MASK_BIT; 152 153 ish_reg_write(dev, IPC_REG_PIMR_BXT, host_pimr_val); 154 } 155 } 156 157 /** 158 * ishtp_fw_is_ready() - Check if FW ready 159 * @dev: ISHTP device pointer 160 * 161 * Check if ISH FW is ready 162 * 163 * Return: Read true or false 164 */ 165 static bool ishtp_fw_is_ready(struct ishtp_device *dev) 166 { 167 uint32_t ish_status = _ish_read_fw_sts_reg(dev); 168 169 return IPC_IS_ISH_ILUP(ish_status) && 170 IPC_IS_ISH_ISHTP_READY(ish_status); 171 } 172 173 /** 174 * ish_set_host_rdy() - Indicate host ready 175 * @dev: ISHTP device pointer 176 * 177 * Set host ready indication to FW 178 */ 179 static void ish_set_host_rdy(struct ishtp_device *dev) 180 { 181 uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM); 182 183 IPC_SET_HOST_READY(host_status); 184 ish_reg_write(dev, IPC_REG_HOST_COMM, host_status); 185 } 186 187 /** 188 * ish_clr_host_rdy() - Indicate host not ready 189 * @dev: ISHTP device pointer 190 * 191 * Send host not ready indication to FW 192 */ 193 static void ish_clr_host_rdy(struct ishtp_device *dev) 194 { 195 uint32_t host_status = ish_reg_read(dev, IPC_REG_HOST_COMM); 196 197 IPC_CLEAR_HOST_READY(host_status); 198 ish_reg_write(dev, IPC_REG_HOST_COMM, host_status); 199 } 200 201 /** 202 * _ishtp_read_hdr() - Read message header 203 * @dev: ISHTP device pointer 204 * 205 * Read header of 32bit length 206 * 207 * Return: Read register value 208 */ 209 static uint32_t _ishtp_read_hdr(const struct ishtp_device *dev) 210 { 211 return ish_reg_read(dev, IPC_REG_ISH2HOST_MSG); 212 } 213 214 /** 215 * _ishtp_read - Read message 216 * @dev: ISHTP device pointer 217 * @buffer: message buffer 218 * @buffer_length: length of message buffer 219 * 220 * Read message from FW 221 * 222 * Return: Always 0 223 */ 224 static int _ishtp_read(struct ishtp_device *dev, unsigned char *buffer, 225 unsigned long buffer_length) 226 { 227 uint32_t i; 228 uint32_t *r_buf = (uint32_t *)buffer; 229 uint32_t msg_offs; 230 231 msg_offs = IPC_REG_ISH2HOST_MSG + sizeof(struct ishtp_msg_hdr); 232 for (i = 0; i < buffer_length; i += sizeof(uint32_t)) 233 *r_buf++ = ish_reg_read(dev, msg_offs + i); 234 235 return 0; 236 } 237 238 /** 239 * write_ipc_from_queue() - try to write ipc msg from Tx queue to device 240 * @dev: ishtp device pointer 241 * 242 * Check if DRBL is cleared. if it is - write the first IPC msg, then call 243 * the callback function (unless it's NULL) 244 * 245 * Return: 0 for success else failure code 246 */ 247 static int write_ipc_from_queue(struct ishtp_device *dev) 248 { 249 struct wr_msg_ctl_info *ipc_link; 250 unsigned long length; 251 unsigned long rem; 252 unsigned long flags; 253 uint32_t doorbell_val; 254 uint32_t *r_buf; 255 uint32_t reg_addr; 256 int i; 257 void (*ipc_send_compl)(void *); 258 void *ipc_send_compl_prm; 259 static int out_ipc_locked; 260 unsigned long out_ipc_flags; 261 262 if (dev->dev_state == ISHTP_DEV_DISABLED) 263 return -EINVAL; 264 265 spin_lock_irqsave(&dev->out_ipc_spinlock, out_ipc_flags); 266 if (out_ipc_locked) { 267 spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); 268 return -EBUSY; 269 } 270 out_ipc_locked = 1; 271 if (!ish_is_input_ready(dev)) { 272 out_ipc_locked = 0; 273 spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); 274 return -EBUSY; 275 } 276 spin_unlock_irqrestore(&dev->out_ipc_spinlock, out_ipc_flags); 277 278 spin_lock_irqsave(&dev->wr_processing_spinlock, flags); 279 /* 280 * if tx send list is empty - return 0; 281 * may happen, as RX_COMPLETE handler doesn't check list emptiness. 282 */ 283 if (list_empty(&dev->wr_processing_list_head.link)) { 284 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 285 out_ipc_locked = 0; 286 return 0; 287 } 288 289 ipc_link = list_entry(dev->wr_processing_list_head.link.next, 290 struct wr_msg_ctl_info, link); 291 /* first 4 bytes of the data is the doorbell value (IPC header) */ 292 length = ipc_link->length - sizeof(uint32_t); 293 doorbell_val = *(uint32_t *)ipc_link->inline_data; 294 r_buf = (uint32_t *)(ipc_link->inline_data + sizeof(uint32_t)); 295 296 /* If sending MNG_SYNC_FW_CLOCK, update clock again */ 297 if (IPC_HEADER_GET_PROTOCOL(doorbell_val) == IPC_PROTOCOL_MNG && 298 IPC_HEADER_GET_MNG_CMD(doorbell_val) == MNG_SYNC_FW_CLOCK) { 299 uint64_t usec_system, usec_utc; 300 struct ipc_time_update_msg time_update; 301 struct time_sync_format ts_format; 302 303 usec_system = ktime_to_us(ktime_get_boottime()); 304 usec_utc = ktime_to_us(ktime_get_real()); 305 ts_format.ts1_source = HOST_SYSTEM_TIME_USEC; 306 ts_format.ts2_source = HOST_UTC_TIME_USEC; 307 ts_format.reserved = 0; 308 309 time_update.primary_host_time = usec_system; 310 time_update.secondary_host_time = usec_utc; 311 time_update.sync_info = ts_format; 312 313 memcpy(r_buf, &time_update, 314 sizeof(struct ipc_time_update_msg)); 315 } 316 317 for (i = 0, reg_addr = IPC_REG_HOST2ISH_MSG; i < length >> 2; i++, 318 reg_addr += 4) 319 ish_reg_write(dev, reg_addr, r_buf[i]); 320 321 rem = length & 0x3; 322 if (rem > 0) { 323 uint32_t reg = 0; 324 325 memcpy(®, &r_buf[length >> 2], rem); 326 ish_reg_write(dev, reg_addr, reg); 327 } 328 /* Flush writes to msg registers and doorbell */ 329 ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 330 331 /* Update IPC counters */ 332 ++dev->ipc_tx_cnt; 333 dev->ipc_tx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); 334 335 ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, doorbell_val); 336 out_ipc_locked = 0; 337 338 ipc_send_compl = ipc_link->ipc_send_compl; 339 ipc_send_compl_prm = ipc_link->ipc_send_compl_prm; 340 list_del_init(&ipc_link->link); 341 list_add_tail(&ipc_link->link, &dev->wr_free_list_head.link); 342 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 343 344 /* 345 * callback will be called out of spinlock, 346 * after ipc_link returned to free list 347 */ 348 if (ipc_send_compl) 349 ipc_send_compl(ipc_send_compl_prm); 350 351 return 0; 352 } 353 354 /** 355 * write_ipc_to_queue() - write ipc msg to Tx queue 356 * @dev: ishtp device instance 357 * @ipc_send_compl: Send complete callback 358 * @ipc_send_compl_prm: Parameter to send in complete callback 359 * @msg: Pointer to message 360 * @length: Length of message 361 * 362 * Recived msg with IPC (and upper protocol) header and add it to the device 363 * Tx-to-write list then try to send the first IPC waiting msg 364 * (if DRBL is cleared) 365 * This function returns negative value for failure (means free list 366 * is empty, or msg too long) and 0 for success. 367 * 368 * Return: 0 for success else failure code 369 */ 370 static int write_ipc_to_queue(struct ishtp_device *dev, 371 void (*ipc_send_compl)(void *), void *ipc_send_compl_prm, 372 unsigned char *msg, int length) 373 { 374 struct wr_msg_ctl_info *ipc_link; 375 unsigned long flags; 376 377 if (length > IPC_FULL_MSG_SIZE) 378 return -EMSGSIZE; 379 380 spin_lock_irqsave(&dev->wr_processing_spinlock, flags); 381 if (list_empty(&dev->wr_free_list_head.link)) { 382 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 383 return -ENOMEM; 384 } 385 ipc_link = list_entry(dev->wr_free_list_head.link.next, 386 struct wr_msg_ctl_info, link); 387 list_del_init(&ipc_link->link); 388 389 ipc_link->ipc_send_compl = ipc_send_compl; 390 ipc_link->ipc_send_compl_prm = ipc_send_compl_prm; 391 ipc_link->length = length; 392 memcpy(ipc_link->inline_data, msg, length); 393 394 list_add_tail(&ipc_link->link, &dev->wr_processing_list_head.link); 395 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 396 397 write_ipc_from_queue(dev); 398 399 return 0; 400 } 401 402 /** 403 * ipc_send_mng_msg() - Send management message 404 * @dev: ishtp device instance 405 * @msg_code: Message code 406 * @msg: Pointer to message 407 * @size: Length of message 408 * 409 * Send management message to FW 410 * 411 * Return: 0 for success else failure code 412 */ 413 static int ipc_send_mng_msg(struct ishtp_device *dev, uint32_t msg_code, 414 void *msg, size_t size) 415 { 416 unsigned char ipc_msg[IPC_FULL_MSG_SIZE]; 417 uint32_t drbl_val = IPC_BUILD_MNG_MSG(msg_code, size); 418 419 memcpy(ipc_msg, &drbl_val, sizeof(uint32_t)); 420 memcpy(ipc_msg + sizeof(uint32_t), msg, size); 421 return write_ipc_to_queue(dev, NULL, NULL, ipc_msg, 422 sizeof(uint32_t) + size); 423 } 424 425 #define WAIT_FOR_FW_RDY 0x1 426 #define WAIT_FOR_INPUT_RDY 0x2 427 428 /** 429 * timed_wait_for_timeout() - wait special event with timeout 430 * @dev: ISHTP device pointer 431 * @condition: indicate the condition for waiting 432 * @timeinc: time slice for every wait cycle, in ms 433 * @timeout: time in ms for timeout 434 * 435 * This function will check special event to be ready in a loop, the loop 436 * period is specificd in timeinc. Wait timeout will causes failure. 437 * 438 * Return: 0 for success else failure code 439 */ 440 static int timed_wait_for_timeout(struct ishtp_device *dev, int condition, 441 unsigned int timeinc, unsigned int timeout) 442 { 443 bool complete = false; 444 int ret; 445 446 do { 447 if (condition == WAIT_FOR_FW_RDY) { 448 complete = ishtp_fw_is_ready(dev); 449 } else if (condition == WAIT_FOR_INPUT_RDY) { 450 complete = ish_is_input_ready(dev); 451 } else { 452 ret = -EINVAL; 453 goto out; 454 } 455 456 if (!complete) { 457 unsigned long left_time; 458 459 left_time = msleep_interruptible(timeinc); 460 timeout -= (timeinc - left_time); 461 } 462 } while (!complete && timeout > 0); 463 464 if (complete) 465 ret = 0; 466 else 467 ret = -EBUSY; 468 469 out: 470 return ret; 471 } 472 473 #define TIME_SLICE_FOR_FW_RDY_MS 100 474 #define TIME_SLICE_FOR_INPUT_RDY_MS 100 475 #define TIMEOUT_FOR_FW_RDY_MS 2000 476 #define TIMEOUT_FOR_INPUT_RDY_MS 2000 477 478 /** 479 * ish_fw_reset_handler() - FW reset handler 480 * @dev: ishtp device pointer 481 * 482 * Handle FW reset 483 * 484 * Return: 0 for success else failure code 485 */ 486 static int ish_fw_reset_handler(struct ishtp_device *dev) 487 { 488 uint32_t reset_id; 489 unsigned long flags; 490 struct wr_msg_ctl_info *processing, *next; 491 492 /* Read reset ID */ 493 reset_id = ish_reg_read(dev, IPC_REG_ISH2HOST_MSG) & 0xFFFF; 494 495 /* Clear IPC output queue */ 496 spin_lock_irqsave(&dev->wr_processing_spinlock, flags); 497 list_for_each_entry_safe(processing, next, 498 &dev->wr_processing_list_head.link, link) { 499 list_move_tail(&processing->link, &dev->wr_free_list_head.link); 500 } 501 spin_unlock_irqrestore(&dev->wr_processing_spinlock, flags); 502 503 /* ISHTP notification in IPC_RESET */ 504 ishtp_reset_handler(dev); 505 506 if (!ish_is_input_ready(dev)) 507 timed_wait_for_timeout(dev, WAIT_FOR_INPUT_RDY, 508 TIME_SLICE_FOR_INPUT_RDY_MS, TIMEOUT_FOR_INPUT_RDY_MS); 509 510 /* ISH FW is dead */ 511 if (!ish_is_input_ready(dev)) 512 return -EPIPE; 513 /* 514 * Set HOST2ISH.ILUP. Apparently we need this BEFORE sending 515 * RESET_NOTIFY_ACK - FW will be checking for it 516 */ 517 ish_set_host_rdy(dev); 518 /* Send RESET_NOTIFY_ACK (with reset_id) */ 519 ipc_send_mng_msg(dev, MNG_RESET_NOTIFY_ACK, &reset_id, 520 sizeof(uint32_t)); 521 522 /* Wait for ISH FW'es ILUP and ISHTP_READY */ 523 timed_wait_for_timeout(dev, WAIT_FOR_FW_RDY, 524 TIME_SLICE_FOR_FW_RDY_MS, TIMEOUT_FOR_FW_RDY_MS); 525 if (!ishtp_fw_is_ready(dev)) { 526 /* ISH FW is dead */ 527 uint32_t ish_status; 528 529 ish_status = _ish_read_fw_sts_reg(dev); 530 dev_err(dev->devc, 531 "[ishtp-ish]: completed reset, ISH is dead (FWSTS = %08X)\n", 532 ish_status); 533 return -ENODEV; 534 } 535 return 0; 536 } 537 538 #define TIMEOUT_FOR_HW_RDY_MS 300 539 540 /** 541 * ish_fw_reset_work_fn() - FW reset worker function 542 * @unused: not used 543 * 544 * Call ish_fw_reset_handler to complete FW reset 545 */ 546 static void fw_reset_work_fn(struct work_struct *unused) 547 { 548 int rv; 549 550 rv = ish_fw_reset_handler(ishtp_dev); 551 if (!rv) { 552 /* ISH is ILUP & ISHTP-ready. Restart ISHTP */ 553 msleep_interruptible(TIMEOUT_FOR_HW_RDY_MS); 554 ishtp_dev->recvd_hw_ready = 1; 555 wake_up_interruptible(&ishtp_dev->wait_hw_ready); 556 557 /* ISHTP notification in IPC_RESET sequence completion */ 558 ishtp_reset_compl_handler(ishtp_dev); 559 } else 560 dev_err(ishtp_dev->devc, "[ishtp-ish]: FW reset failed (%d)\n", 561 rv); 562 } 563 564 /** 565 * _ish_sync_fw_clock() -Sync FW clock with the OS clock 566 * @dev: ishtp device pointer 567 * 568 * Sync FW and OS time 569 */ 570 static void _ish_sync_fw_clock(struct ishtp_device *dev) 571 { 572 static unsigned long prev_sync; 573 uint64_t usec; 574 575 if (prev_sync && jiffies - prev_sync < 20 * HZ) 576 return; 577 578 prev_sync = jiffies; 579 usec = ktime_to_us(ktime_get_boottime()); 580 ipc_send_mng_msg(dev, MNG_SYNC_FW_CLOCK, &usec, sizeof(uint64_t)); 581 } 582 583 /** 584 * recv_ipc() - Receive and process IPC management messages 585 * @dev: ishtp device instance 586 * @doorbell_val: doorbell value 587 * 588 * This function runs in ISR context. 589 * NOTE: Any other mng command than reset_notify and reset_notify_ack 590 * won't wake BH handler 591 */ 592 static void recv_ipc(struct ishtp_device *dev, uint32_t doorbell_val) 593 { 594 uint32_t mng_cmd; 595 596 mng_cmd = IPC_HEADER_GET_MNG_CMD(doorbell_val); 597 598 switch (mng_cmd) { 599 default: 600 break; 601 602 case MNG_RX_CMPL_INDICATION: 603 if (dev->suspend_flag) { 604 dev->suspend_flag = 0; 605 wake_up_interruptible(&dev->suspend_wait); 606 } 607 if (dev->resume_flag) { 608 dev->resume_flag = 0; 609 wake_up_interruptible(&dev->resume_wait); 610 } 611 612 write_ipc_from_queue(dev); 613 break; 614 615 case MNG_RESET_NOTIFY: 616 if (!ishtp_dev) { 617 ishtp_dev = dev; 618 INIT_WORK(&fw_reset_work, fw_reset_work_fn); 619 } 620 schedule_work(&fw_reset_work); 621 break; 622 623 case MNG_RESET_NOTIFY_ACK: 624 dev->recvd_hw_ready = 1; 625 wake_up_interruptible(&dev->wait_hw_ready); 626 break; 627 } 628 } 629 630 /** 631 * ish_irq_handler() - ISH IRQ handler 632 * @irq: irq number 633 * @dev_id: ishtp device pointer 634 * 635 * ISH IRQ handler. If interrupt is generated and is for ISH it will process 636 * the interrupt. 637 */ 638 irqreturn_t ish_irq_handler(int irq, void *dev_id) 639 { 640 struct ishtp_device *dev = dev_id; 641 uint32_t doorbell_val; 642 bool interrupt_generated; 643 644 /* Check that it's interrupt from ISH (may be shared) */ 645 interrupt_generated = check_generated_interrupt(dev); 646 647 if (!interrupt_generated) 648 return IRQ_NONE; 649 650 doorbell_val = ish_reg_read(dev, IPC_REG_ISH2HOST_DRBL); 651 if (!IPC_IS_BUSY(doorbell_val)) 652 return IRQ_HANDLED; 653 654 if (dev->dev_state == ISHTP_DEV_DISABLED) 655 return IRQ_HANDLED; 656 657 /* Sanity check: IPC dgram length in header */ 658 if (IPC_HEADER_GET_LENGTH(doorbell_val) > IPC_PAYLOAD_SIZE) { 659 dev_err(dev->devc, 660 "IPC hdr - bad length: %u; dropped\n", 661 (unsigned int)IPC_HEADER_GET_LENGTH(doorbell_val)); 662 goto eoi; 663 } 664 665 switch (IPC_HEADER_GET_PROTOCOL(doorbell_val)) { 666 default: 667 break; 668 case IPC_PROTOCOL_MNG: 669 recv_ipc(dev, doorbell_val); 670 break; 671 case IPC_PROTOCOL_ISHTP: 672 ishtp_recv(dev); 673 break; 674 } 675 676 eoi: 677 /* Update IPC counters */ 678 ++dev->ipc_rx_cnt; 679 dev->ipc_rx_bytes_cnt += IPC_HEADER_GET_LENGTH(doorbell_val); 680 681 ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0); 682 /* Flush write to doorbell */ 683 ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 684 685 return IRQ_HANDLED; 686 } 687 688 /** 689 * ish_disable_dma() - disable dma communication between host and ISHFW 690 * @dev: ishtp device pointer 691 * 692 * Clear the dma enable bit and wait for dma inactive. 693 * 694 * Return: 0 for success else error code. 695 */ 696 static int ish_disable_dma(struct ishtp_device *dev) 697 { 698 unsigned int dma_delay; 699 700 /* Clear the dma enable bit */ 701 ish_reg_write(dev, IPC_REG_ISH_RMP2, 0); 702 703 /* wait for dma inactive */ 704 for (dma_delay = 0; dma_delay < MAX_DMA_DELAY && 705 _ish_read_fw_sts_reg(dev) & (IPC_ISH_IN_DMA); 706 dma_delay += 5) 707 mdelay(5); 708 709 if (dma_delay >= MAX_DMA_DELAY) { 710 dev_err(dev->devc, 711 "Wait for DMA inactive timeout\n"); 712 return -EBUSY; 713 } 714 715 return 0; 716 } 717 718 /** 719 * ish_wakeup() - wakeup ishfw from waiting-for-host state 720 * @dev: ishtp device pointer 721 * 722 * Set the dma enable bit and send a void message to FW, 723 * it wil wakeup FW from waiting-for-host state. 724 */ 725 static void ish_wakeup(struct ishtp_device *dev) 726 { 727 /* Set dma enable bit */ 728 ish_reg_write(dev, IPC_REG_ISH_RMP2, IPC_RMP2_DMA_ENABLED); 729 730 /* 731 * Send 0 IPC message so that ISH FW wakes up if it was already 732 * asleep. 733 */ 734 ish_reg_write(dev, IPC_REG_HOST2ISH_DRBL, IPC_DRBL_BUSY_BIT); 735 736 /* Flush writes to doorbell and REMAP2 */ 737 ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 738 } 739 740 /** 741 * _ish_hw_reset() - HW reset 742 * @dev: ishtp device pointer 743 * 744 * Reset ISH HW to recover if any error 745 * 746 * Return: 0 for success else error fault code 747 */ 748 static int _ish_hw_reset(struct ishtp_device *dev) 749 { 750 struct pci_dev *pdev = dev->pdev; 751 int rv; 752 uint16_t csr; 753 754 if (!pdev) 755 return -ENODEV; 756 757 rv = pci_reset_function(pdev); 758 if (!rv) 759 dev->dev_state = ISHTP_DEV_RESETTING; 760 761 if (!pdev->pm_cap) { 762 dev_err(&pdev->dev, "Can't reset - no PM caps\n"); 763 return -EINVAL; 764 } 765 766 /* Disable dma communication between FW and host */ 767 if (ish_disable_dma(dev)) { 768 dev_err(&pdev->dev, 769 "Can't reset - stuck with DMA in-progress\n"); 770 return -EBUSY; 771 } 772 773 pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &csr); 774 775 csr &= ~PCI_PM_CTRL_STATE_MASK; 776 csr |= PCI_D3hot; 777 pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); 778 779 mdelay(pdev->d3_delay); 780 781 csr &= ~PCI_PM_CTRL_STATE_MASK; 782 csr |= PCI_D0; 783 pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, csr); 784 785 /* Now we can enable ISH DMA operation and wakeup ISHFW */ 786 ish_wakeup(dev); 787 788 return 0; 789 } 790 791 /** 792 * _ish_ipc_reset() - IPC reset 793 * @dev: ishtp device pointer 794 * 795 * Resets host and fw IPC and upper layers 796 * 797 * Return: 0 for success else error fault code 798 */ 799 static int _ish_ipc_reset(struct ishtp_device *dev) 800 { 801 struct ipc_rst_payload_type ipc_mng_msg; 802 int rv = 0; 803 804 ipc_mng_msg.reset_id = 1; 805 ipc_mng_msg.reserved = 0; 806 807 set_host_ready(dev); 808 809 /* Clear the incoming doorbell */ 810 ish_reg_write(dev, IPC_REG_ISH2HOST_DRBL, 0); 811 /* Flush write to doorbell */ 812 ish_reg_read(dev, IPC_REG_ISH_HOST_FWSTS); 813 814 dev->recvd_hw_ready = 0; 815 816 /* send message */ 817 rv = ipc_send_mng_msg(dev, MNG_RESET_NOTIFY, &ipc_mng_msg, 818 sizeof(struct ipc_rst_payload_type)); 819 if (rv) { 820 dev_err(dev->devc, "Failed to send IPC MNG_RESET_NOTIFY\n"); 821 return rv; 822 } 823 824 wait_event_interruptible_timeout(dev->wait_hw_ready, 825 dev->recvd_hw_ready, 2 * HZ); 826 if (!dev->recvd_hw_ready) { 827 dev_err(dev->devc, "Timed out waiting for HW ready\n"); 828 rv = -ENODEV; 829 } 830 831 return rv; 832 } 833 834 /** 835 * ish_hw_start() -Start ISH HW 836 * @dev: ishtp device pointer 837 * 838 * Set host to ready state and wait for FW reset 839 * 840 * Return: 0 for success else error fault code 841 */ 842 int ish_hw_start(struct ishtp_device *dev) 843 { 844 ish_set_host_rdy(dev); 845 846 /* After that we can enable ISH DMA operation and wakeup ISHFW */ 847 ish_wakeup(dev); 848 849 set_host_ready(dev); 850 851 /* wait for FW-initiated reset flow */ 852 if (!dev->recvd_hw_ready) 853 wait_event_interruptible_timeout(dev->wait_hw_ready, 854 dev->recvd_hw_ready, 855 10 * HZ); 856 857 if (!dev->recvd_hw_ready) { 858 dev_err(dev->devc, 859 "[ishtp-ish]: Timed out waiting for FW-initiated reset\n"); 860 return -ENODEV; 861 } 862 863 return 0; 864 } 865 866 /** 867 * ish_ipc_get_header() -Get doorbell value 868 * @dev: ishtp device pointer 869 * @length: length of message 870 * @busy: busy status 871 * 872 * Get door bell value from message header 873 * 874 * Return: door bell value 875 */ 876 static uint32_t ish_ipc_get_header(struct ishtp_device *dev, int length, 877 int busy) 878 { 879 uint32_t drbl_val; 880 881 drbl_val = IPC_BUILD_HEADER(length, IPC_PROTOCOL_ISHTP, busy); 882 883 return drbl_val; 884 } 885 886 static const struct ishtp_hw_ops ish_hw_ops = { 887 .hw_reset = _ish_hw_reset, 888 .ipc_reset = _ish_ipc_reset, 889 .ipc_get_header = ish_ipc_get_header, 890 .ishtp_read = _ishtp_read, 891 .write = write_ipc_to_queue, 892 .get_fw_status = _ish_read_fw_sts_reg, 893 .sync_fw_clock = _ish_sync_fw_clock, 894 .ishtp_read_hdr = _ishtp_read_hdr 895 }; 896 897 /** 898 * ish_dev_init() -Initialize ISH devoce 899 * @pdev: PCI device 900 * 901 * Allocate ISHTP device and initialize IPC processing 902 * 903 * Return: ISHTP device instance on success else NULL 904 */ 905 struct ishtp_device *ish_dev_init(struct pci_dev *pdev) 906 { 907 struct ishtp_device *dev; 908 int i; 909 910 dev = devm_kzalloc(&pdev->dev, 911 sizeof(struct ishtp_device) + sizeof(struct ish_hw), 912 GFP_KERNEL); 913 if (!dev) 914 return NULL; 915 916 ishtp_device_init(dev); 917 918 init_waitqueue_head(&dev->wait_hw_ready); 919 920 spin_lock_init(&dev->wr_processing_spinlock); 921 spin_lock_init(&dev->out_ipc_spinlock); 922 923 /* Init IPC processing and free lists */ 924 INIT_LIST_HEAD(&dev->wr_processing_list_head.link); 925 INIT_LIST_HEAD(&dev->wr_free_list_head.link); 926 for (i = 0; i < IPC_TX_FIFO_SIZE; ++i) { 927 struct wr_msg_ctl_info *tx_buf; 928 929 tx_buf = devm_kzalloc(&pdev->dev, 930 sizeof(struct wr_msg_ctl_info), 931 GFP_KERNEL); 932 if (!tx_buf) { 933 /* 934 * IPC buffers may be limited or not available 935 * at all - although this shouldn't happen 936 */ 937 dev_err(dev->devc, 938 "[ishtp-ish]: failure in Tx FIFO allocations (%d)\n", 939 i); 940 break; 941 } 942 list_add_tail(&tx_buf->link, &dev->wr_free_list_head.link); 943 } 944 945 dev->ops = &ish_hw_ops; 946 dev->devc = &pdev->dev; 947 dev->mtu = IPC_PAYLOAD_SIZE - sizeof(struct ishtp_msg_hdr); 948 return dev; 949 } 950 951 /** 952 * ish_device_disable() - Disable ISH device 953 * @dev: ISHTP device pointer 954 * 955 * Disable ISH by clearing host ready to inform firmware. 956 */ 957 void ish_device_disable(struct ishtp_device *dev) 958 { 959 struct pci_dev *pdev = dev->pdev; 960 961 if (!pdev) 962 return; 963 964 /* Disable dma communication between FW and host */ 965 if (ish_disable_dma(dev)) { 966 dev_err(&pdev->dev, 967 "Can't reset - stuck with DMA in-progress\n"); 968 return; 969 } 970 971 /* Put ISH to D3hot state for power saving */ 972 pci_set_power_state(pdev, PCI_D3hot); 973 974 dev->dev_state = ISHTP_DEV_DISABLED; 975 ish_clr_host_rdy(dev); 976 } 977