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

1 // SPDX-License-Identifier: GPL-2.0-only
22 #include "vsc-tp.h"
38 (sizeof(struct vsc_tp_packet) + le16_to_cpu((pkt)->len) + VSC_TP_CRC_SIZE)
44 (len + sizeof(struct vsc_tp_packet) + VSC_TP_CRC_SIZE - offset + VSC_TP_PACKET_PADDING_SIZE)
48 __u8 cmd; member
89 { "wakeuphost-gpios", &wakeuphost_gpio, 1 },
90 { "wakeuphostint-gpios", &wakeuphostint_gpio, 1 },
91 { "resetfw-gpios", &resetfw_gpio, 1 },
92 { "wakeupfw-gpios", &wakeupfw, 1 },
101 gpiod_set_value_cansleep(tp->wakeupfw, 0); in vsc_tp_wakeup_request()
103 ret = wait_event_timeout(tp->xfer_wait, in vsc_tp_wakeup_request()
104 atomic_read(&tp->assert_cnt) && in vsc_tp_wakeup_request()
105 gpiod_get_value_cansleep(tp->wakeuphost), in vsc_tp_wakeup_request()
108 return -ETIMEDOUT; in vsc_tp_wakeup_request()
115 atomic_dec_if_positive(&tp->assert_cnt); in vsc_tp_wakeup_release()
117 gpiod_set_value_cansleep(tp->wakeupfw, 1); in vsc_tp_wakeup_release()
131 return spi_sync_locked(tp->spi, &msg); in vsc_tp_dev_xfer()
139 u8 *src, *crc_src, *rx_buf = tp->rx_buf; in vsc_tp_xfer_helper()
160 src_len = next_xfer_len - (src - rx_buf); in vsc_tp_xfer_helper()
169 src_len -= cpy_len; in vsc_tp_xfer_helper()
171 dst_len -= cpy_len; in vsc_tp_xfer_helper()
192 int remain = sizeof(ack) + le16_to_cpu(ack.len) - offset; in vsc_tp_xfer_helper()
198 src_len -= cpy_len; in vsc_tp_xfer_helper()
217 } while (next_xfer_len > 0 && --count_down); in vsc_tp_xfer_helper()
220 return -EAGAIN; in vsc_tp_xfer_helper()
222 if (~recv_crc != crc || le32_to_cpu(ack.seq) != tp->seq) { in vsc_tp_xfer_helper()
223 dev_err(&tp->spi->dev, "recv crc or seq error\n"); in vsc_tp_xfer_helper()
224 return -EINVAL; in vsc_tp_xfer_helper()
227 if (ack.cmd == VSC_TP_CMD_ACK || ack.cmd == VSC_TP_CMD_NACK || in vsc_tp_xfer_helper()
228 ack.cmd == VSC_TP_CMD_BUSY) { in vsc_tp_xfer_helper()
229 dev_err(&tp->spi->dev, "recv cmd ack error\n"); in vsc_tp_xfer_helper()
230 return -EAGAIN; in vsc_tp_xfer_helper()
237 * vsc_tp_xfer - transfer data to firmware
239 * @cmd: the command to be sent to the device
247 int vsc_tp_xfer(struct vsc_tp *tp, u8 cmd, const void *obuf, size_t olen, in vsc_tp_xfer() argument
250 struct vsc_tp_packet *pkt = tp->tx_buf; in vsc_tp_xfer()
255 return -EINVAL; in vsc_tp_xfer()
257 guard(mutex)(&tp->mutex); in vsc_tp_xfer()
259 pkt->sync = VSC_TP_PACKET_SYNC; in vsc_tp_xfer()
260 pkt->cmd = cmd; in vsc_tp_xfer()
261 pkt->len = cpu_to_le16(olen); in vsc_tp_xfer()
262 pkt->seq = cpu_to_le32(++tp->seq); in vsc_tp_xfer()
263 memcpy(pkt->buf, obuf, olen); in vsc_tp_xfer()
266 memcpy(pkt->buf + olen, &crc, sizeof(crc)); in vsc_tp_xfer()
270 dev_err(&tp->spi->dev, "wakeup firmware failed ret: %d\n", ret); in vsc_tp_xfer()
281 * vsc_tp_rom_xfer - transfer data to rom code
294 return -EINVAL; in vsc_tp_rom_xfer()
296 guard(mutex)(&tp->mutex); in vsc_tp_rom_xfer()
299 cpu_to_be32_array(tp->tx_buf, obuf, words); in vsc_tp_rom_xfer()
304 tp->wakeuphost); in vsc_tp_rom_xfer()
306 dev_err(&tp->spi->dev, "wait rom failed ret: %d\n", ret); in vsc_tp_rom_xfer()
310 ret = vsc_tp_dev_xfer(tp, tp->tx_buf, tp->rx_buf, len); in vsc_tp_rom_xfer()
315 cpu_to_be32_array(ibuf, tp->rx_buf, words); in vsc_tp_rom_xfer()
321 * vsc_tp_reset - reset vsc transport layer
326 disable_irq(tp->spi->irq); in vsc_tp_reset()
329 gpiod_set_value_cansleep(tp->resetfw, 0); in vsc_tp_reset()
331 gpiod_set_value_cansleep(tp->resetfw, 1); in vsc_tp_reset()
337 * Set default host wakeup pin to non-active in vsc_tp_reset()
340 gpiod_set_value_cansleep(tp->wakeupfw, 1); in vsc_tp_reset()
342 atomic_set(&tp->assert_cnt, 0); in vsc_tp_reset()
344 enable_irq(tp->spi->irq); in vsc_tp_reset()
349 * vsc_tp_need_read - check if device has data to sent
355 if (!atomic_read(&tp->assert_cnt)) in vsc_tp_need_read()
357 if (!gpiod_get_value_cansleep(tp->wakeuphost)) in vsc_tp_need_read()
359 if (!gpiod_get_value_cansleep(tp->wakeupfw)) in vsc_tp_need_read()
367 * vsc_tp_register_event_cb - register a callback function to receive event
376 tp->event_notify = event_cb; in vsc_tp_register_event_cb()
377 tp->event_notify_context = context; in vsc_tp_register_event_cb()
384 * vsc_tp_intr_synchronize - synchronize vsc_tp interrupt
389 synchronize_irq(tp->spi->irq); in vsc_tp_intr_synchronize()
394 * vsc_tp_intr_enable - enable vsc_tp interrupt
399 enable_irq(tp->spi->irq); in vsc_tp_intr_enable()
404 * vsc_tp_intr_disable - disable vsc_tp interrupt
409 disable_irq(tp->spi->irq); in vsc_tp_intr_disable()
417 atomic_inc(&tp->assert_cnt); in vsc_tp_isr()
419 wake_up(&tp->xfer_wait); in vsc_tp_isr()
428 if (tp->event_notify) in vsc_tp_thread_isr()
429 tp->event_notify(tp->event_notify_context); in vsc_tp_thread_isr()
446 struct device *dev = &spi->dev; in vsc_tp_probe()
454 return -ENOMEM; in vsc_tp_probe()
456 tp->tx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL); in vsc_tp_probe()
457 if (!tp->tx_buf) in vsc_tp_probe()
458 return -ENOMEM; in vsc_tp_probe()
460 tp->rx_buf = devm_kzalloc(dev, VSC_TP_MAX_XFER_SIZE, GFP_KERNEL); in vsc_tp_probe()
461 if (!tp->rx_buf) in vsc_tp_probe()
462 return -ENOMEM; in vsc_tp_probe()
468 tp->wakeuphost = devm_gpiod_get(dev, "wakeuphost", GPIOD_IN); in vsc_tp_probe()
469 if (IS_ERR(tp->wakeuphost)) in vsc_tp_probe()
470 return PTR_ERR(tp->wakeuphost); in vsc_tp_probe()
472 tp->resetfw = devm_gpiod_get(dev, "resetfw", GPIOD_OUT_HIGH); in vsc_tp_probe()
473 if (IS_ERR(tp->resetfw)) in vsc_tp_probe()
474 return PTR_ERR(tp->resetfw); in vsc_tp_probe()
476 tp->wakeupfw = devm_gpiod_get(dev, "wakeupfw", GPIOD_OUT_HIGH); in vsc_tp_probe()
477 if (IS_ERR(tp->wakeupfw)) in vsc_tp_probe()
478 return PTR_ERR(tp->wakeupfw); in vsc_tp_probe()
480 atomic_set(&tp->assert_cnt, 0); in vsc_tp_probe()
481 init_waitqueue_head(&tp->xfer_wait); in vsc_tp_probe()
482 tp->spi = spi; in vsc_tp_probe()
484 irq_set_status_flags(spi->irq, IRQ_DISABLE_UNLAZY); in vsc_tp_probe()
485 ret = devm_request_threaded_irq(dev, spi->irq, vsc_tp_isr, in vsc_tp_probe()
492 mutex_init(&tp->mutex); in vsc_tp_probe()
498 ret = -ENODEV; in vsc_tp_probe()
514 tp->pdev = pdev; in vsc_tp_probe()
520 mutex_destroy(&tp->mutex); in vsc_tp_probe()
529 platform_device_unregister(tp->pdev); in vsc_tp_remove()
531 mutex_destroy(&tp->mutex); in vsc_tp_remove()
547 .name = "vsc-tp",