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