Lines Matching +full:spi +full:- +full:tx +full:- +full:delay +full:- +full:us

1 // SPDX-License-Identifier: (GPL-2.0+ OR MIT)
6 #include <linux/delay.h>
17 #include <linux/spi/spi.h>
19 #include <linux/platform_data/spi-rockchip.h>
40 struct spi_device *spi; member
55 spidev->ready_status = status; in spidev_mst_slave_ready_status()
69 return spidev->ready_status; in spidev_mst_check_slave_ready()
81 dev_err(&spidev->spi->dev, "timeout and reset slave\n"); in spidev_mst_wait_for_slave_ready()
83 return -ETIMEDOUT; in spidev_mst_wait_for_slave_ready()
91 struct spi_device *spi = spidev->spi; in spidev_mst_write() local
108 ret = spi_sync(spi, &m); in spidev_mst_write()
115 struct spi_device *spi = spidev->spi; in spidev_mst_write_bypass() local
127 ret = spi_sync(spi, &m); in spidev_mst_write_bypass()
134 struct spi_device *spi = spidev->spi; in spidev_mst_read() local
151 ret = spi_sync(spi, &m); in spidev_mst_read()
160 struct spi_device *spi = spidev->spi; in spidev_slv_write_and_read() local
177 ret = spi_sync(spi, &m); in spidev_slv_write_and_read()
184 struct spi_obj_ctrl *ctrl = (struct spi_obj_ctrl *)spidev->ctrlbuf; in spidev_rkmst_reset_slave()
186 ctrl->cmd = SPI_OBJ_CTRL_CMD_INIT; in spidev_rkmst_reset_slave()
196 struct spi_obj_ctrl *ctrl = (struct spi_obj_ctrl *)spidev->ctrlbuf; in spidev_rkmst_ctrl()
197 struct spi_device *spi = spidev->spi; in spidev_rkmst_ctrl() local
200 if (spidev->verbose) in spidev_rkmst_ctrl()
201 dev_err(&spi->dev, "ctrl cmd=%x addr=0x%x data=0x%x\n", cmd, addr, data); in spidev_rkmst_ctrl()
204 ctrl->cmd = cmd; in spidev_rkmst_ctrl()
205 ctrl->addr = addr; in spidev_rkmst_ctrl()
206 ctrl->data = data; in spidev_rkmst_ctrl()
209 dev_err(&spi->dev, "ctrl cmd=%x addr=0x%x data=0x%x, ret=%d\n", cmd, addr, data, ret); in spidev_rkmst_ctrl()
210 return -EIO; in spidev_rkmst_ctrl()
216 static int spidev_rkmst_xfer(struct spidev_rkmst_data *spidev, void *tx, in spidev_rkmst_xfer() argument
219 struct spi_device *spi = spidev->spi; in spidev_rkmst_xfer() local
223 if (tx && rx) in spidev_rkmst_xfer()
227 else if (tx) in spidev_rkmst_xfer()
230 return -EINVAL; in spidev_rkmst_xfer()
236 return -EIO; in spidev_rkmst_xfer()
239 if (spidev->verbose) in spidev_rkmst_xfer()
240 dev_err(&spi->dev, "xfer len=0x%x\n", len); in spidev_rkmst_xfer()
249 ret = spidev_mst_write(spidev, tx, len); in spidev_rkmst_xfer()
254 ret = spidev_slv_write_and_read(spidev, tx, rx, len); in spidev_rkmst_xfer()
259 dev_err(&spi->dev, "%s unknown\n", __func__); in spidev_rkmst_xfer()
264 dev_err(&spi->dev, "xfer cmd=%x addr=0x%x len=0x%x, ret=%d\n", in spidev_rkmst_xfer()
274 struct spi_device *spi; in spidev_rkmst_misc_write() local
281 return -EINVAL; in spidev_rkmst_misc_write()
283 spidev = filp->private_data; in spidev_rkmst_misc_write()
286 return -ESHUTDOWN; in spidev_rkmst_misc_write()
288 spi = spidev->spi; in spidev_rkmst_misc_write()
291 return -EFAULT; in spidev_rkmst_misc_write()
306 tmp[n - 1] = 0; in spidev_rkmst_misc_write()
312 return -EINVAL; in spidev_rkmst_misc_write()
315 return -EINVAL; in spidev_rkmst_misc_write()
318 spidev->verbose = true; in spidev_rkmst_misc_write()
320 spidev->verbose = false; in spidev_rkmst_misc_write()
327 return -EINVAL; in spidev_rkmst_misc_write()
330 return -EINVAL; in spidev_rkmst_misc_write()
332 return -EINVAL; in spidev_rkmst_misc_write()
335 dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]); in spidev_rkmst_misc_write()
336 return -EINVAL; in spidev_rkmst_misc_write()
340 dev_err(&spi->dev, "rxbuf print out of size\n"); in spidev_rkmst_misc_write()
341 return -EINVAL; in spidev_rkmst_misc_write()
344 spidev_rkmst_xfer(spidev, NULL, spidev->rxbuf, addr, len); in spidev_rkmst_misc_write()
346 print_hex_dump(KERN_ERR, "m-r: ", in spidev_rkmst_misc_write()
350 spidev->rxbuf, in spidev_rkmst_misc_write()
357 return -EINVAL; in spidev_rkmst_misc_write()
360 return -EINVAL; in spidev_rkmst_misc_write()
362 return -EINVAL; in spidev_rkmst_misc_write()
365 dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]); in spidev_rkmst_misc_write()
366 return -EINVAL; in spidev_rkmst_misc_write()
370 dev_err(&spi->dev, "rxbuf print out of size\n"); in spidev_rkmst_misc_write()
371 return -EINVAL; in spidev_rkmst_misc_write()
375 spidev->txbuf[i] = i & 0xFF; in spidev_rkmst_misc_write()
376 ((u32 *)spidev->txbuf)[0] = addr; in spidev_rkmst_misc_write()
378 spidev_rkmst_xfer(spidev, spidev->txbuf, NULL, addr, len); in spidev_rkmst_misc_write()
383 return -EINVAL; in spidev_rkmst_misc_write()
386 return -EINVAL; in spidev_rkmst_misc_write()
388 return -EINVAL; in spidev_rkmst_misc_write()
391 dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]); in spidev_rkmst_misc_write()
392 return -EINVAL; in spidev_rkmst_misc_write()
396 dev_err(&spi->dev, "rxbuf print out of size\n"); in spidev_rkmst_misc_write()
397 return -EINVAL; in spidev_rkmst_misc_write()
401 spidev->txbuf[i] = i & 0xFF; in spidev_rkmst_misc_write()
402 ((u32 *)spidev->txbuf)[0] = addr; in spidev_rkmst_misc_write()
404 spidev_rkmst_xfer(spidev, spidev->txbuf, spidev->rxbuf, addr, len); in spidev_rkmst_misc_write()
406 print_hex_dump(KERN_ERR, "m-d: ", in spidev_rkmst_misc_write()
410 spidev->rxbuf, in spidev_rkmst_misc_write()
416 unsigned long us = 0; in spidev_rkmst_misc_write() local
423 return -EINVAL; in spidev_rkmst_misc_write()
426 return -EINVAL; in spidev_rkmst_misc_write()
429 return -EINVAL; in spidev_rkmst_misc_write()
432 dev_err(&spi->dev, "param invalid,%s %s\n", argv[0], argv[1]); in spidev_rkmst_misc_write()
433 return -EINVAL; in spidev_rkmst_misc_write()
437 dev_err(&spi->dev, "rxbuf print out of size\n"); in spidev_rkmst_misc_write()
438 return -EINVAL; in spidev_rkmst_misc_write()
443 return -ENOMEM; in spidev_rkmst_misc_write()
449 prandom_bytes(spidev->txbuf, len); in spidev_rkmst_misc_write()
450 spidev_rkmst_xfer(spidev, spidev->txbuf, spidev->rxbuf, addr, len); in spidev_rkmst_misc_write()
451 if (memcmp(spidev->rxbuf, tempbuf, len)) { in spidev_rkmst_misc_write()
452 dev_err(&spi->dev, "dulplex autotest failed, loops=%d\n", i); in spidev_rkmst_misc_write()
453 print_hex_dump(KERN_ERR, "m-d-t: ", in spidev_rkmst_misc_write()
457 spidev->txbuf, in spidev_rkmst_misc_write()
460 print_hex_dump(KERN_ERR, "m-d-r: ", in spidev_rkmst_misc_write()
464 spidev->rxbuf, in spidev_rkmst_misc_write()
467 print_hex_dump(KERN_ERR, "m-d-c: ", in spidev_rkmst_misc_write()
476 memcpy(tempbuf, spidev->txbuf, len); in spidev_rkmst_misc_write()
480 us = ktime_to_us(cost_time); in spidev_rkmst_misc_write()
483 do_div(bytes, us); in spidev_rkmst_misc_write()
485 dev_err(&spi->dev, "dulplex test pass, cost=%ldus, speed=%lldKB/S, %ldus/loops\n", in spidev_rkmst_misc_write()
486 us, bytes, us / loops); in spidev_rkmst_misc_write()
490 prandom_bytes(spidev->txbuf, len); in spidev_rkmst_misc_write()
491 spidev_rkmst_xfer(spidev, spidev->txbuf, NULL, addr, len); in spidev_rkmst_misc_write()
492 spidev_rkmst_xfer(spidev, NULL, spidev->rxbuf, addr, len); in spidev_rkmst_misc_write()
493 if (memcmp(spidev->rxbuf, spidev->txbuf, len)) { in spidev_rkmst_misc_write()
494 dev_err(&spi->dev, "read/write autotest failed, loops=%d\n", i); in spidev_rkmst_misc_write()
495 print_hex_dump(KERN_ERR, "m-d-t: ", in spidev_rkmst_misc_write()
499 spidev->txbuf, in spidev_rkmst_misc_write()
502 print_hex_dump(KERN_ERR, "m-d-r: ", in spidev_rkmst_misc_write()
506 spidev->rxbuf, in spidev_rkmst_misc_write()
514 us = ktime_to_us(cost_time); in spidev_rkmst_misc_write()
517 do_div(bytes, us); in spidev_rkmst_misc_write()
519 dev_err(&spi->dev, "read/write test pass, cost=%ldus, speed=%lldKB/S, %ldus/loops\n", in spidev_rkmst_misc_write()
520 us, bytes, us / loops); in spidev_rkmst_misc_write()
523 dev_err(&spi->dev, "unknown command\n"); in spidev_rkmst_misc_write()
531 struct miscdevice *miscdev = filp->private_data; in spidev_rkmst_misc_open()
535 filp->private_data = spidev; in spidev_rkmst_misc_open()
545 static int spidev_rkmst_probe(struct spi_device *spi) in spidev_rkmst_probe() argument
550 if (!spi) in spidev_rkmst_probe()
551 return -ENOMEM; in spidev_rkmst_probe()
553 spidev = devm_kzalloc(&spi->dev, sizeof(struct spidev_rkmst_data), GFP_KERNEL); in spidev_rkmst_probe()
555 return -ENOMEM; in spidev_rkmst_probe()
557 spidev->ctrlbuf = devm_kzalloc(&spi->dev, SPI_OBJ_MAX_XFER_SIZE, GFP_KERNEL); in spidev_rkmst_probe()
558 if (!spidev->ctrlbuf) in spidev_rkmst_probe()
559 return -ENOMEM; in spidev_rkmst_probe()
561 spidev->rxbuf = devm_kzalloc(&spi->dev, SPI_OBJ_APP_RAM_SIZE, GFP_KERNEL | GFP_DMA); in spidev_rkmst_probe()
562 if (!spidev->rxbuf) in spidev_rkmst_probe()
563 return -ENOMEM; in spidev_rkmst_probe()
565 spidev->txbuf = devm_kzalloc(&spi->dev, SPI_OBJ_MAX_XFER_SIZE, GFP_KERNEL); in spidev_rkmst_probe()
566 if (!spidev->txbuf) in spidev_rkmst_probe()
567 return -ENOMEM; in spidev_rkmst_probe()
569 spidev->spi = spi; in spidev_rkmst_probe()
570 spidev->dev = &spi->dev; in spidev_rkmst_probe()
573 spidev->ready = devm_gpiod_get_optional(&spi->dev, "ready", GPIOD_IN); in spidev_rkmst_probe()
574 if (IS_ERR(spidev->ready)) in spidev_rkmst_probe()
575 return dev_err_probe(&spi->dev, PTR_ERR(spidev->ready), in spidev_rkmst_probe()
576 "invalid ready-gpios property in node\n"); in spidev_rkmst_probe()
578 spidev->ready_irqnum = gpiod_to_irq(spidev->ready); in spidev_rkmst_probe()
579 ret = devm_request_irq(&spi->dev, spidev->ready_irqnum, spidev_mst_slave_ready_interrupt, in spidev_rkmst_probe()
580 IRQF_TRIGGER_FALLING, "spidev-mst-ready-in", spidev); in spidev_rkmst_probe()
582 dev_err(&spi->dev, "request ready irq failed\n"); in spidev_rkmst_probe()
585 dev_set_drvdata(&spi->dev, spidev); in spidev_rkmst_probe()
587 dev_err(&spi->dev, "mode=%d, max_speed_hz=%d\n", spi->mode, spi->max_speed_hz); in spidev_rkmst_probe()
589 spidev->misc_dev.minor = MISC_DYNAMIC_MINOR; in spidev_rkmst_probe()
590 spidev->misc_dev.name = "spidev_rkmst_misc"; in spidev_rkmst_probe()
591 spidev->misc_dev.fops = &spidev_rkmst_misc_fops; in spidev_rkmst_probe()
592 spidev->misc_dev.parent = &spi->dev; in spidev_rkmst_probe()
593 ret = misc_register(&spidev->misc_dev); in spidev_rkmst_probe()
595 dev_err(&spi->dev, "fail to register misc device\n"); in spidev_rkmst_probe()
604 static int spidev_rkmst_remove(struct spi_device *spi) in spidev_rkmst_remove() argument
606 struct spidev_rkmst_data *spidev = dev_get_drvdata(&spi->dev); in spidev_rkmst_remove()
608 misc_deregister(&spidev->misc_dev); in spidev_rkmst_remove()
615 { .compatible = "rockchip,spi-obj-master", },
633 MODULE_AUTHOR("Jon Lin <jon.lin@rock-chips.com>");
634 MODULE_DESCRIPTION("ROCKCHIP SPI Object Master Driver");
636 MODULE_ALIAS("spi:spidev_rkmst");