Lines Matching +full:layer +full:- +full:buffer +full:- +full:offset
1 // SPDX-License-Identifier: GPL-2.0-only
4 * Intel Visual Sensing Controller Transport Layer Linux driver
22 #include "vsc-tp.h"
38 (sizeof(struct vsc_tp_packet) + le16_to_cpu((pkt)->len) + VSC_TP_CRC_SIZE)
43 #define VSC_TP_NEXT_XFER_LEN(len, offset) \ argument
44 (len + sizeof(struct vsc_tp_packet) + VSC_TP_CRC_SIZE - offset + VSC_TP_PACKET_PADDING_SIZE)
68 /* command buffer */
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()
137 int ret, offset = 0, cpy_len, src_len, dst_len = sizeof(struct vsc_tp_packet); in vsc_tp_xfer_helper() local
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()
173 if (offset < sizeof(ack)) { in vsc_tp_xfer_helper()
174 offset += cpy_len; in vsc_tp_xfer_helper()
187 } else if (offset < sizeof(ack) + le16_to_cpu(ack.len)) { in vsc_tp_xfer_helper()
188 offset += cpy_len; in vsc_tp_xfer_helper()
192 int remain = sizeof(ack) + le16_to_cpu(ack.len) - offset; in vsc_tp_xfer_helper()
195 offset += cpy_len; in vsc_tp_xfer_helper()
198 src_len -= cpy_len; in vsc_tp_xfer_helper()
205 next_xfer_len = VSC_TP_NEXT_XFER_LEN(le16_to_cpu(ack.len), offset); in vsc_tp_xfer_helper()
206 } else if (offset < sizeof(ack) + le16_to_cpu(ack.len) + VSC_TP_CRC_SIZE) { in vsc_tp_xfer_helper()
207 offset += cpy_len; in vsc_tp_xfer_helper()
214 next_xfer_len = VSC_TP_NEXT_XFER_LEN(le16_to_cpu(ack.len), offset); 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()
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
240 * @obuf: the tx buffer to be sent to the device
241 * @olen: the length of tx buffer
242 * @ibuf: the rx buffer to receive from the device
243 * @ilen: the length of rx buffer
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
283 * @obuf: the data buffer to be sent to the device
284 * @ibuf: the buffer to receive data from the device
285 * @len: the length of tx buffer and rx buffer
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",
555 MODULE_DESCRIPTION("Intel Visual Sensing Controller Transport Layer");