Lines Matching +full:cmd +full:- +full:gpios

1 // SPDX-License-Identifier: GPL-2.0-only
22 #include "vsc-tp.h"
39 (sizeof(struct vsc_tp_packet_hdr) + le16_to_cpu((pkt)->hdr.len) + VSC_TP_CRC_SIZE)
45 (len + sizeof(struct vsc_tp_packet_hdr) + VSC_TP_CRC_SIZE - offset + VSC_TP_PACKET_PADDING_SIZE)
49 __u8 cmd; member
56 __u8 buf[VSC_TP_MAX_XFER_SIZE - sizeof(struct vsc_tp_packet_hdr)];
94 { "wakeuphost-gpios", &wakeuphost_gpio, 1 },
95 { "wakeuphostint-gpios", &wakeuphostint_gpio, 1 },
96 { "resetfw-gpios", &resetfw_gpio, 1 },
97 { "wakeupfw-gpios", &wakeupfw, 1 },
105 atomic_inc(&tp->assert_cnt); in vsc_tp_isr()
107 wake_up(&tp->xfer_wait); in vsc_tp_isr()
116 if (tp->event_notify) in vsc_tp_thread_isr()
117 tp->event_notify(tp->event_notify_context); in vsc_tp_thread_isr()
127 gpiod_set_value_cansleep(tp->wakeupfw, 0); in vsc_tp_wakeup_request()
129 ret = wait_event_timeout(tp->xfer_wait, in vsc_tp_wakeup_request()
130 atomic_read(&tp->assert_cnt), in vsc_tp_wakeup_request()
133 return -ETIMEDOUT; in vsc_tp_wakeup_request()
138 tp->wakeuphost); in vsc_tp_wakeup_request()
143 atomic_dec_if_positive(&tp->assert_cnt); in vsc_tp_wakeup_release()
145 gpiod_set_value_cansleep(tp->wakeupfw, 1); in vsc_tp_wakeup_release()
159 return spi_sync_locked(tp->spi, &msg); in vsc_tp_dev_xfer()
167 u8 *src, *crc_src, *rx_buf = (u8 *)tp->rx_buf; in vsc_tp_xfer_helper()
188 src_len = next_xfer_len - (src - rx_buf); in vsc_tp_xfer_helper()
197 src_len -= cpy_len; in vsc_tp_xfer_helper()
199 dst_len -= cpy_len; in vsc_tp_xfer_helper()
220 int remain = sizeof(ack) + le16_to_cpu(ack.len) - offset; in vsc_tp_xfer_helper()
226 src_len -= cpy_len; in vsc_tp_xfer_helper()
245 } while (next_xfer_len > 0 && --count_down); in vsc_tp_xfer_helper()
248 return -EAGAIN; in vsc_tp_xfer_helper()
250 if (~recv_crc != crc || le32_to_cpu(ack.seq) != tp->seq) { in vsc_tp_xfer_helper()
251 dev_err(&tp->spi->dev, "recv crc or seq error\n"); in vsc_tp_xfer_helper()
252 return -EINVAL; in vsc_tp_xfer_helper()
255 if (ack.cmd == VSC_TP_CMD_ACK || ack.cmd == VSC_TP_CMD_NACK || in vsc_tp_xfer_helper()
256 ack.cmd == VSC_TP_CMD_BUSY) { in vsc_tp_xfer_helper()
257 dev_err(&tp->spi->dev, "recv cmd ack error\n"); in vsc_tp_xfer_helper()
258 return -EAGAIN; in vsc_tp_xfer_helper()
265 * vsc_tp_xfer - transfer data to firmware
267 * @cmd: the command to be sent to the device
275 int vsc_tp_xfer(struct vsc_tp *tp, u8 cmd, const void *obuf, size_t olen, in vsc_tp_xfer() argument
278 struct vsc_tp_packet *pkt = tp->tx_buf; in vsc_tp_xfer()
283 return -EINVAL; in vsc_tp_xfer()
285 guard(mutex)(&tp->mutex); in vsc_tp_xfer()
287 pkt->hdr.sync = VSC_TP_PACKET_SYNC; in vsc_tp_xfer()
288 pkt->hdr.cmd = cmd; in vsc_tp_xfer()
289 pkt->hdr.len = cpu_to_le16(olen); in vsc_tp_xfer()
290 pkt->hdr.seq = cpu_to_le32(++tp->seq); in vsc_tp_xfer()
291 memcpy(pkt->buf, obuf, olen); in vsc_tp_xfer()
294 memcpy(pkt->buf + olen, &crc, sizeof(crc)); in vsc_tp_xfer()
298 dev_err(&tp->spi->dev, "wakeup firmware failed ret: %d\n", ret); in vsc_tp_xfer()
309 * vsc_tp_rom_xfer - transfer data to rom code
322 return -EINVAL; in vsc_tp_rom_xfer()
324 guard(mutex)(&tp->mutex); in vsc_tp_rom_xfer()
327 cpu_to_be32_array((u32 *)tp->tx_buf, obuf, words); in vsc_tp_rom_xfer()
332 tp->wakeuphost); in vsc_tp_rom_xfer()
334 dev_err(&tp->spi->dev, "wait rom failed ret: %d\n", ret); in vsc_tp_rom_xfer()
338 ret = vsc_tp_dev_xfer(tp, tp->tx_buf, ibuf ? tp->rx_buf : NULL, len); in vsc_tp_rom_xfer()
343 be32_to_cpu_array(ibuf, (u32 *)tp->rx_buf, words); in vsc_tp_rom_xfer()
349 * vsc_tp_reset - reset vsc transport layer
354 disable_irq(tp->spi->irq); in vsc_tp_reset()
357 gpiod_set_value_cansleep(tp->resetfw, 0); in vsc_tp_reset()
359 gpiod_set_value_cansleep(tp->resetfw, 1); in vsc_tp_reset()
365 * Set default host wakeup pin to non-active in vsc_tp_reset()
368 gpiod_set_value_cansleep(tp->wakeupfw, 1); in vsc_tp_reset()
370 atomic_set(&tp->assert_cnt, 0); in vsc_tp_reset()
375 * vsc_tp_need_read - check if device has data to sent
381 if (!atomic_read(&tp->assert_cnt)) in vsc_tp_need_read()
383 if (!gpiod_get_value_cansleep(tp->wakeuphost)) in vsc_tp_need_read()
385 if (!gpiod_get_value_cansleep(tp->wakeupfw)) in vsc_tp_need_read()
393 * vsc_tp_register_event_cb - register a callback function to receive event
402 tp->event_notify = event_cb; in vsc_tp_register_event_cb()
403 tp->event_notify_context = context; in vsc_tp_register_event_cb()
410 * vsc_tp_request_irq - request irq for vsc_tp device
415 struct spi_device *spi = tp->spi; in vsc_tp_request_irq()
416 struct device *dev = &spi->dev; in vsc_tp_request_irq()
419 irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY); in vsc_tp_request_irq()
420 ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr, in vsc_tp_request_irq()
431 * vsc_tp_free_irq - free irq for vsc_tp device
436 free_irq(tp->spi->irq, tp); in vsc_tp_free_irq()
441 * vsc_tp_intr_synchronize - synchronize vsc_tp interrupt
446 synchronize_irq(tp->spi->irq); in vsc_tp_intr_synchronize()
451 * vsc_tp_intr_enable - enable vsc_tp interrupt
456 enable_irq(tp->spi->irq); in vsc_tp_intr_enable()
461 * vsc_tp_intr_disable - disable vsc_tp interrupt
466 disable_irq(tp->spi->irq); in vsc_tp_intr_disable()
488 struct device *dev = &spi->dev; in vsc_tp_probe()
495 return -ENOMEM; in vsc_tp_probe()
497 tp->tx_buf = devm_kzalloc(dev, sizeof(*tp->tx_buf), GFP_KERNEL); in vsc_tp_probe()
498 if (!tp->tx_buf) in vsc_tp_probe()
499 return -ENOMEM; in vsc_tp_probe()
501 tp->rx_buf = devm_kzalloc(dev, sizeof(*tp->rx_buf), GFP_KERNEL); in vsc_tp_probe()
502 if (!tp->rx_buf) in vsc_tp_probe()
503 return -ENOMEM; in vsc_tp_probe()
509 tp->wakeuphost = devm_gpiod_get(dev, "wakeuphostint", GPIOD_IN); in vsc_tp_probe()
510 if (IS_ERR(tp->wakeuphost)) in vsc_tp_probe()
511 return PTR_ERR(tp->wakeuphost); in vsc_tp_probe()
513 tp->resetfw = devm_gpiod_get(dev, "resetfw", GPIOD_OUT_HIGH); in vsc_tp_probe()
514 if (IS_ERR(tp->resetfw)) in vsc_tp_probe()
515 return PTR_ERR(tp->resetfw); in vsc_tp_probe()
517 tp->wakeupfw = devm_gpiod_get(dev, "wakeupfw", GPIOD_OUT_HIGH); in vsc_tp_probe()
518 if (IS_ERR(tp->wakeupfw)) in vsc_tp_probe()
519 return PTR_ERR(tp->wakeupfw); in vsc_tp_probe()
521 atomic_set(&tp->assert_cnt, 0); in vsc_tp_probe()
522 init_waitqueue_head(&tp->xfer_wait); in vsc_tp_probe()
523 tp->spi = spi; in vsc_tp_probe()
525 irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY); in vsc_tp_probe()
526 ret = request_threaded_irq(spi->irq, vsc_tp_isr, vsc_tp_thread_isr, in vsc_tp_probe()
532 mutex_init(&tp->mutex); in vsc_tp_probe()
538 ret = -ENODEV; in vsc_tp_probe()
549 tp->pdev = pdev; in vsc_tp_probe()
555 mutex_destroy(&tp->mutex); in vsc_tp_probe()
557 free_irq(spi->irq, tp); in vsc_tp_probe()
566 platform_device_unregister(tp->pdev); in vsc_tp_remove()
568 mutex_destroy(&tp->mutex); in vsc_tp_remove()
570 free_irq(spi->irq, tp); in vsc_tp_remove()
577 platform_device_unregister(tp->pdev); in vsc_tp_shutdown()
579 mutex_destroy(&tp->mutex); in vsc_tp_shutdown()
583 free_irq(spi->irq, tp); in vsc_tp_shutdown()
600 .name = "vsc-tp",