File Index
Files and directories
Sign in
FILE

ipc.c

File preview with syntax highlighting.

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