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