diff options
author | Mark Brown <broonie@linaro.org> | 2013-10-25 04:51:29 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-10-25 04:51:29 -0400 |
commit | 8211e6b8facd9d0da3e8f6e51657cba8b0af19da (patch) | |
tree | 2f73c2ae7cbbab24bd93998f6f63264eee5c1269 | |
parent | c25b2c9eb36502f81c59df764074a475249a4550 (diff) | |
parent | 0732a9d2a1551e3be5fd8a3ea680deb3d9e56193 (diff) |
Merge remote-tracking branch 'spi/topic/loop' into spi-next
-rw-r--r-- | drivers/spi/Kconfig | 2 | ||||
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 236 | ||||
-rw-r--r-- | drivers/spi/spi.c | 130 | ||||
-rw-r--r-- | include/linux/spi/spi.h | 32 | ||||
-rw-r--r-- | include/trace/events/spi.h | 156 |
5 files changed, 428 insertions, 128 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index c463d364b3dd..bf2b27f40160 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -394,7 +394,7 @@ config SPI_S3C24XX_FIQ | |||
394 | 394 | ||
395 | config SPI_S3C64XX | 395 | config SPI_S3C64XX |
396 | tristate "Samsung S3C64XX series type SPI" | 396 | tristate "Samsung S3C64XX series type SPI" |
397 | depends on (ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5P64X0 || ARCH_EXYNOS) | 397 | depends on PLAT_SAMSUNG |
398 | select S3C64XX_DMA if ARCH_S3C64XX | 398 | select S3C64XX_DMA if ARCH_S3C64XX |
399 | help | 399 | help |
400 | SPI driver for Samsung S3C64XX and newer SoCs. | 400 | SPI driver for Samsung S3C64XX and newer SoCs. |
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index ae07c3afe956..508f51fc5704 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c | |||
@@ -205,7 +205,6 @@ struct s3c64xx_spi_driver_data { | |||
205 | #endif | 205 | #endif |
206 | struct s3c64xx_spi_port_config *port_conf; | 206 | struct s3c64xx_spi_port_config *port_conf; |
207 | unsigned int port_id; | 207 | unsigned int port_id; |
208 | unsigned long gpios[4]; | ||
209 | bool cs_gpio; | 208 | bool cs_gpio; |
210 | }; | 209 | }; |
211 | 210 | ||
@@ -559,25 +558,18 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, | |||
559 | static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, | 558 | static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, |
560 | struct spi_device *spi) | 559 | struct spi_device *spi) |
561 | { | 560 | { |
562 | struct s3c64xx_spi_csinfo *cs; | ||
563 | |||
564 | if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */ | 561 | if (sdd->tgl_spi != NULL) { /* If last device toggled after mssg */ |
565 | if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ | 562 | if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ |
566 | /* Deselect the last toggled device */ | 563 | /* Deselect the last toggled device */ |
567 | cs = sdd->tgl_spi->controller_data; | 564 | if (spi->cs_gpio >= 0) |
568 | if (sdd->cs_gpio) | 565 | gpio_set_value(spi->cs_gpio, |
569 | gpio_set_value(cs->line, | ||
570 | spi->mode & SPI_CS_HIGH ? 0 : 1); | 566 | spi->mode & SPI_CS_HIGH ? 0 : 1); |
571 | } | 567 | } |
572 | sdd->tgl_spi = NULL; | 568 | sdd->tgl_spi = NULL; |
573 | } | 569 | } |
574 | 570 | ||
575 | cs = spi->controller_data; | 571 | if (spi->cs_gpio >= 0) |
576 | if (sdd->cs_gpio) | 572 | gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 1 : 0); |
577 | gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); | ||
578 | |||
579 | /* Start the signals */ | ||
580 | writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); | ||
581 | } | 573 | } |
582 | 574 | ||
583 | static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, | 575 | static u32 s3c64xx_spi_wait_for_timeout(struct s3c64xx_spi_driver_data *sdd, |
@@ -702,16 +694,11 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, | |||
702 | static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, | 694 | static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, |
703 | struct spi_device *spi) | 695 | struct spi_device *spi) |
704 | { | 696 | { |
705 | struct s3c64xx_spi_csinfo *cs = spi->controller_data; | ||
706 | |||
707 | if (sdd->tgl_spi == spi) | 697 | if (sdd->tgl_spi == spi) |
708 | sdd->tgl_spi = NULL; | 698 | sdd->tgl_spi = NULL; |
709 | 699 | ||
710 | if (sdd->cs_gpio) | 700 | if (spi->cs_gpio >= 0) |
711 | gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); | 701 | gpio_set_value(spi->cs_gpio, spi->mode & SPI_CS_HIGH ? 0 : 1); |
712 | |||
713 | /* Quiese the signals */ | ||
714 | writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); | ||
715 | } | 702 | } |
716 | 703 | ||
717 | static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) | 704 | static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) |
@@ -862,16 +849,12 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd, | |||
862 | } | 849 | } |
863 | } | 850 | } |
864 | 851 | ||
865 | static int s3c64xx_spi_transfer_one_message(struct spi_master *master, | 852 | static int s3c64xx_spi_prepare_message(struct spi_master *master, |
866 | struct spi_message *msg) | 853 | struct spi_message *msg) |
867 | { | 854 | { |
868 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | 855 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
869 | struct spi_device *spi = msg->spi; | 856 | struct spi_device *spi = msg->spi; |
870 | struct s3c64xx_spi_csinfo *cs = spi->controller_data; | 857 | struct s3c64xx_spi_csinfo *cs = spi->controller_data; |
871 | struct spi_transfer *xfer; | ||
872 | int status = 0, cs_toggle = 0; | ||
873 | u32 speed; | ||
874 | u8 bpw; | ||
875 | 858 | ||
876 | /* If Master's(controller) state differs from that needed by Slave */ | 859 | /* If Master's(controller) state differs from that needed by Slave */ |
877 | if (sdd->cur_speed != spi->max_speed_hz | 860 | if (sdd->cur_speed != spi->max_speed_hz |
@@ -887,106 +870,98 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master, | |||
887 | if (s3c64xx_spi_map_mssg(sdd, msg)) { | 870 | if (s3c64xx_spi_map_mssg(sdd, msg)) { |
888 | dev_err(&spi->dev, | 871 | dev_err(&spi->dev, |
889 | "Xfer: Unable to map message buffers!\n"); | 872 | "Xfer: Unable to map message buffers!\n"); |
890 | status = -ENOMEM; | 873 | return -ENOMEM; |
891 | goto out; | ||
892 | } | 874 | } |
893 | 875 | ||
894 | /* Configure feedback delay */ | 876 | /* Configure feedback delay */ |
895 | writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); | 877 | writel(cs->fb_delay & 0x3, sdd->regs + S3C64XX_SPI_FB_CLK); |
896 | 878 | ||
897 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 879 | return 0; |
898 | 880 | } | |
899 | unsigned long flags; | ||
900 | int use_dma; | ||
901 | |||
902 | INIT_COMPLETION(sdd->xfer_completion); | ||
903 | |||
904 | /* Only BPW and Speed may change across transfers */ | ||
905 | bpw = xfer->bits_per_word; | ||
906 | speed = xfer->speed_hz ? : spi->max_speed_hz; | ||
907 | |||
908 | if (xfer->len % (bpw / 8)) { | ||
909 | dev_err(&spi->dev, | ||
910 | "Xfer length(%u) not a multiple of word size(%u)\n", | ||
911 | xfer->len, bpw / 8); | ||
912 | status = -EIO; | ||
913 | goto out; | ||
914 | } | ||
915 | 881 | ||
916 | if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { | 882 | static int s3c64xx_spi_transfer_one(struct spi_master *master, |
917 | sdd->cur_bpw = bpw; | 883 | struct spi_device *spi, |
918 | sdd->cur_speed = speed; | 884 | struct spi_transfer *xfer) |
919 | s3c64xx_spi_config(sdd); | 885 | { |
920 | } | 886 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
887 | int status; | ||
888 | u32 speed; | ||
889 | u8 bpw; | ||
890 | unsigned long flags; | ||
891 | int use_dma; | ||
921 | 892 | ||
922 | /* Polling method for xfers not bigger than FIFO capacity */ | 893 | INIT_COMPLETION(sdd->xfer_completion); |
923 | use_dma = 0; | ||
924 | if (!is_polling(sdd) && | ||
925 | (sdd->rx_dma.ch && sdd->tx_dma.ch && | ||
926 | (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1)))) | ||
927 | use_dma = 1; | ||
928 | 894 | ||
929 | spin_lock_irqsave(&sdd->lock, flags); | 895 | /* Only BPW and Speed may change across transfers */ |
896 | bpw = xfer->bits_per_word; | ||
897 | speed = xfer->speed_hz ? : spi->max_speed_hz; | ||
930 | 898 | ||
931 | /* Pending only which is to be done */ | 899 | if (xfer->len % (bpw / 8)) { |
932 | sdd->state &= ~RXBUSY; | 900 | dev_err(&spi->dev, |
933 | sdd->state &= ~TXBUSY; | 901 | "Xfer length(%u) not a multiple of word size(%u)\n", |
902 | xfer->len, bpw / 8); | ||
903 | return -EIO; | ||
904 | } | ||
934 | 905 | ||
935 | enable_datapath(sdd, spi, xfer, use_dma); | 906 | if (bpw != sdd->cur_bpw || speed != sdd->cur_speed) { |
907 | sdd->cur_bpw = bpw; | ||
908 | sdd->cur_speed = speed; | ||
909 | s3c64xx_spi_config(sdd); | ||
910 | } | ||
936 | 911 | ||
937 | /* Slave Select */ | 912 | /* Polling method for xfers not bigger than FIFO capacity */ |
938 | enable_cs(sdd, spi); | 913 | use_dma = 0; |
914 | if (!is_polling(sdd) && | ||
915 | (sdd->rx_dma.ch && sdd->tx_dma.ch && | ||
916 | (xfer->len > ((FIFO_LVL_MASK(sdd) >> 1) + 1)))) | ||
917 | use_dma = 1; | ||
939 | 918 | ||
940 | spin_unlock_irqrestore(&sdd->lock, flags); | 919 | spin_lock_irqsave(&sdd->lock, flags); |
941 | 920 | ||
942 | status = wait_for_xfer(sdd, xfer, use_dma); | 921 | /* Pending only which is to be done */ |
922 | sdd->state &= ~RXBUSY; | ||
923 | sdd->state &= ~TXBUSY; | ||
943 | 924 | ||
944 | if (status) { | 925 | enable_datapath(sdd, spi, xfer, use_dma); |
945 | dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", | ||
946 | xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, | ||
947 | (sdd->state & RXBUSY) ? 'f' : 'p', | ||
948 | (sdd->state & TXBUSY) ? 'f' : 'p', | ||
949 | xfer->len); | ||
950 | 926 | ||
951 | if (use_dma) { | 927 | /* Start the signals */ |
952 | if (xfer->tx_buf != NULL | 928 | writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); |
953 | && (sdd->state & TXBUSY)) | ||
954 | s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma); | ||
955 | if (xfer->rx_buf != NULL | ||
956 | && (sdd->state & RXBUSY)) | ||
957 | s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma); | ||
958 | } | ||
959 | 929 | ||
960 | goto out; | 930 | /* Start the signals */ |
961 | } | 931 | writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL); |
962 | 932 | ||
963 | if (xfer->delay_usecs) | 933 | spin_unlock_irqrestore(&sdd->lock, flags); |
964 | udelay(xfer->delay_usecs); | ||
965 | 934 | ||
966 | if (xfer->cs_change) { | 935 | status = wait_for_xfer(sdd, xfer, use_dma); |
967 | /* Hint that the next mssg is gonna be | 936 | |
968 | for the same device */ | 937 | if (status) { |
969 | if (list_is_last(&xfer->transfer_list, | 938 | dev_err(&spi->dev, "I/O Error: rx-%d tx-%d res:rx-%c tx-%c len-%d\n", |
970 | &msg->transfers)) | 939 | xfer->rx_buf ? 1 : 0, xfer->tx_buf ? 1 : 0, |
971 | cs_toggle = 1; | 940 | (sdd->state & RXBUSY) ? 'f' : 'p', |
941 | (sdd->state & TXBUSY) ? 'f' : 'p', | ||
942 | xfer->len); | ||
943 | |||
944 | if (use_dma) { | ||
945 | if (xfer->tx_buf != NULL | ||
946 | && (sdd->state & TXBUSY)) | ||
947 | s3c64xx_spi_dma_stop(sdd, &sdd->tx_dma); | ||
948 | if (xfer->rx_buf != NULL | ||
949 | && (sdd->state & RXBUSY)) | ||
950 | s3c64xx_spi_dma_stop(sdd, &sdd->rx_dma); | ||
972 | } | 951 | } |
973 | 952 | } else { | |
974 | msg->actual_length += xfer->len; | ||
975 | |||
976 | flush_fifo(sdd); | 953 | flush_fifo(sdd); |
977 | } | 954 | } |
978 | 955 | ||
979 | out: | 956 | return status; |
980 | if (!cs_toggle || status) | 957 | } |
981 | disable_cs(sdd, spi); | ||
982 | else | ||
983 | sdd->tgl_spi = spi; | ||
984 | |||
985 | s3c64xx_spi_unmap_mssg(sdd, msg); | ||
986 | 958 | ||
987 | msg->status = status; | 959 | static int s3c64xx_spi_unprepare_message(struct spi_master *master, |
960 | struct spi_message *msg) | ||
961 | { | ||
962 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | ||
988 | 963 | ||
989 | spi_finalize_current_message(master); | 964 | s3c64xx_spi_unmap_mssg(sdd, msg); |
990 | 965 | ||
991 | return 0; | 966 | return 0; |
992 | } | 967 | } |
@@ -1071,6 +1046,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi) | |||
1071 | cs->line, err); | 1046 | cs->line, err); |
1072 | goto err_gpio_req; | 1047 | goto err_gpio_req; |
1073 | } | 1048 | } |
1049 | |||
1050 | spi->cs_gpio = cs->line; | ||
1074 | } | 1051 | } |
1075 | 1052 | ||
1076 | spi_set_ctldata(spi, cs); | 1053 | spi_set_ctldata(spi, cs); |
@@ -1117,12 +1094,14 @@ static int s3c64xx_spi_setup(struct spi_device *spi) | |||
1117 | } | 1094 | } |
1118 | 1095 | ||
1119 | pm_runtime_put(&sdd->pdev->dev); | 1096 | pm_runtime_put(&sdd->pdev->dev); |
1097 | writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); | ||
1120 | disable_cs(sdd, spi); | 1098 | disable_cs(sdd, spi); |
1121 | return 0; | 1099 | return 0; |
1122 | 1100 | ||
1123 | setup_exit: | 1101 | setup_exit: |
1124 | pm_runtime_put(&sdd->pdev->dev); | 1102 | pm_runtime_put(&sdd->pdev->dev); |
1125 | /* setup() returns with device de-selected */ | 1103 | /* setup() returns with device de-selected */ |
1104 | writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL); | ||
1126 | disable_cs(sdd, spi); | 1105 | disable_cs(sdd, spi); |
1127 | 1106 | ||
1128 | gpio_free(cs->line); | 1107 | gpio_free(cs->line); |
@@ -1141,8 +1120,8 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) | |||
1141 | struct s3c64xx_spi_driver_data *sdd; | 1120 | struct s3c64xx_spi_driver_data *sdd; |
1142 | 1121 | ||
1143 | sdd = spi_master_get_devdata(spi->master); | 1122 | sdd = spi_master_get_devdata(spi->master); |
1144 | if (cs && sdd->cs_gpio) { | 1123 | if (spi->cs_gpio) { |
1145 | gpio_free(cs->line); | 1124 | gpio_free(spi->cs_gpio); |
1146 | if (spi->dev.of_node) | 1125 | if (spi->dev.of_node) |
1147 | kfree(cs); | 1126 | kfree(cs); |
1148 | } | 1127 | } |
@@ -1360,7 +1339,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) | |||
1360 | master->setup = s3c64xx_spi_setup; | 1339 | master->setup = s3c64xx_spi_setup; |
1361 | master->cleanup = s3c64xx_spi_cleanup; | 1340 | master->cleanup = s3c64xx_spi_cleanup; |
1362 | master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; | 1341 | master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; |
1363 | master->transfer_one_message = s3c64xx_spi_transfer_one_message; | 1342 | master->prepare_message = s3c64xx_spi_prepare_message; |
1343 | master->transfer_one = s3c64xx_spi_transfer_one; | ||
1344 | master->unprepare_message = s3c64xx_spi_unprepare_message; | ||
1364 | master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; | 1345 | master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; |
1365 | master->num_chipselect = sci->num_cs; | 1346 | master->num_chipselect = sci->num_cs; |
1366 | master->dma_alignment = 8; | 1347 | master->dma_alignment = 8; |
@@ -1432,9 +1413,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) | |||
1432 | pm_runtime_set_active(&pdev->dev); | 1413 | pm_runtime_set_active(&pdev->dev); |
1433 | pm_runtime_enable(&pdev->dev); | 1414 | pm_runtime_enable(&pdev->dev); |
1434 | 1415 | ||
1435 | if (spi_register_master(master)) { | 1416 | ret = devm_spi_register_master(&pdev->dev, master); |
1436 | dev_err(&pdev->dev, "cannot register SPI master\n"); | 1417 | if (ret != 0) { |
1437 | ret = -EBUSY; | 1418 | dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret); |
1438 | goto err3; | 1419 | goto err3; |
1439 | } | 1420 | } |
1440 | 1421 | ||
@@ -1463,16 +1444,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) | |||
1463 | 1444 | ||
1464 | pm_runtime_disable(&pdev->dev); | 1445 | pm_runtime_disable(&pdev->dev); |
1465 | 1446 | ||
1466 | spi_unregister_master(master); | ||
1467 | |||
1468 | writel(0, sdd->regs + S3C64XX_SPI_INT_EN); | 1447 | writel(0, sdd->regs + S3C64XX_SPI_INT_EN); |
1469 | 1448 | ||
1470 | clk_disable_unprepare(sdd->src_clk); | 1449 | clk_disable_unprepare(sdd->src_clk); |
1471 | 1450 | ||
1472 | clk_disable_unprepare(sdd->clk); | 1451 | clk_disable_unprepare(sdd->clk); |
1473 | 1452 | ||
1474 | spi_master_put(master); | ||
1475 | |||
1476 | return 0; | 1453 | return 0; |
1477 | } | 1454 | } |
1478 | 1455 | ||
@@ -1530,9 +1507,17 @@ static int s3c64xx_spi_runtime_resume(struct device *dev) | |||
1530 | { | 1507 | { |
1531 | struct spi_master *master = dev_get_drvdata(dev); | 1508 | struct spi_master *master = dev_get_drvdata(dev); |
1532 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | 1509 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
1510 | int ret; | ||
1533 | 1511 | ||
1534 | clk_prepare_enable(sdd->src_clk); | 1512 | ret = clk_prepare_enable(sdd->src_clk); |
1535 | clk_prepare_enable(sdd->clk); | 1513 | if (ret != 0) |
1514 | return ret; | ||
1515 | |||
1516 | ret = clk_prepare_enable(sdd->clk); | ||
1517 | if (ret != 0) { | ||
1518 | clk_disable_unprepare(sdd->src_clk); | ||
1519 | return ret; | ||
1520 | } | ||
1536 | 1521 | ||
1537 | return 0; | 1522 | return 0; |
1538 | } | 1523 | } |
@@ -1618,6 +1603,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = { | |||
1618 | }; | 1603 | }; |
1619 | 1604 | ||
1620 | static const struct of_device_id s3c64xx_spi_dt_match[] = { | 1605 | static const struct of_device_id s3c64xx_spi_dt_match[] = { |
1606 | { .compatible = "samsung,s3c2443-spi", | ||
1607 | .data = (void *)&s3c2443_spi_port_config, | ||
1608 | }, | ||
1609 | { .compatible = "samsung,s3c6410-spi", | ||
1610 | .data = (void *)&s3c6410_spi_port_config, | ||
1611 | }, | ||
1612 | { .compatible = "samsung,s5pc100-spi", | ||
1613 | .data = (void *)&s5pc100_spi_port_config, | ||
1614 | }, | ||
1615 | { .compatible = "samsung,s5pv210-spi", | ||
1616 | .data = (void *)&s5pv210_spi_port_config, | ||
1617 | }, | ||
1621 | { .compatible = "samsung,exynos4210-spi", | 1618 | { .compatible = "samsung,exynos4210-spi", |
1622 | .data = (void *)&exynos4_spi_port_config, | 1619 | .data = (void *)&exynos4_spi_port_config, |
1623 | }, | 1620 | }, |
@@ -1635,22 +1632,13 @@ static struct platform_driver s3c64xx_spi_driver = { | |||
1635 | .pm = &s3c64xx_spi_pm, | 1632 | .pm = &s3c64xx_spi_pm, |
1636 | .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), | 1633 | .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), |
1637 | }, | 1634 | }, |
1635 | .probe = s3c64xx_spi_probe, | ||
1638 | .remove = s3c64xx_spi_remove, | 1636 | .remove = s3c64xx_spi_remove, |
1639 | .id_table = s3c64xx_spi_driver_ids, | 1637 | .id_table = s3c64xx_spi_driver_ids, |
1640 | }; | 1638 | }; |
1641 | MODULE_ALIAS("platform:s3c64xx-spi"); | 1639 | MODULE_ALIAS("platform:s3c64xx-spi"); |
1642 | 1640 | ||
1643 | static int __init s3c64xx_spi_init(void) | 1641 | module_platform_driver(s3c64xx_spi_driver); |
1644 | { | ||
1645 | return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); | ||
1646 | } | ||
1647 | subsys_initcall(s3c64xx_spi_init); | ||
1648 | |||
1649 | static void __exit s3c64xx_spi_exit(void) | ||
1650 | { | ||
1651 | platform_driver_unregister(&s3c64xx_spi_driver); | ||
1652 | } | ||
1653 | module_exit(s3c64xx_spi_exit); | ||
1654 | 1642 | ||
1655 | MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); | 1643 | MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); |
1656 | MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); | 1644 | MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 99c05f639e1b..8d05accf706c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -39,6 +39,9 @@ | |||
39 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
40 | #include <linux/acpi.h> | 40 | #include <linux/acpi.h> |
41 | 41 | ||
42 | #define CREATE_TRACE_POINTS | ||
43 | #include <trace/events/spi.h> | ||
44 | |||
42 | static void spidev_release(struct device *dev) | 45 | static void spidev_release(struct device *dev) |
43 | { | 46 | { |
44 | struct spi_device *spi = to_spi_device(dev); | 47 | struct spi_device *spi = to_spi_device(dev); |
@@ -525,6 +528,95 @@ int spi_register_board_info(struct spi_board_info const *info, unsigned n) | |||
525 | 528 | ||
526 | /*-------------------------------------------------------------------------*/ | 529 | /*-------------------------------------------------------------------------*/ |
527 | 530 | ||
531 | static void spi_set_cs(struct spi_device *spi, bool enable) | ||
532 | { | ||
533 | if (spi->mode & SPI_CS_HIGH) | ||
534 | enable = !enable; | ||
535 | |||
536 | if (spi->cs_gpio >= 0) | ||
537 | gpio_set_value(spi->cs_gpio, !enable); | ||
538 | else if (spi->master->set_cs) | ||
539 | spi->master->set_cs(spi, !enable); | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * spi_transfer_one_message - Default implementation of transfer_one_message() | ||
544 | * | ||
545 | * This is a standard implementation of transfer_one_message() for | ||
546 | * drivers which impelment a transfer_one() operation. It provides | ||
547 | * standard handling of delays and chip select management. | ||
548 | */ | ||
549 | static int spi_transfer_one_message(struct spi_master *master, | ||
550 | struct spi_message *msg) | ||
551 | { | ||
552 | struct spi_transfer *xfer; | ||
553 | bool cur_cs = true; | ||
554 | bool keep_cs = false; | ||
555 | int ret = 0; | ||
556 | |||
557 | spi_set_cs(msg->spi, true); | ||
558 | |||
559 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | ||
560 | trace_spi_transfer_start(msg, xfer); | ||
561 | |||
562 | INIT_COMPLETION(master->xfer_completion); | ||
563 | |||
564 | ret = master->transfer_one(master, msg->spi, xfer); | ||
565 | if (ret < 0) { | ||
566 | dev_err(&msg->spi->dev, | ||
567 | "SPI transfer failed: %d\n", ret); | ||
568 | goto out; | ||
569 | } | ||
570 | |||
571 | if (ret > 0) | ||
572 | wait_for_completion(&master->xfer_completion); | ||
573 | |||
574 | trace_spi_transfer_stop(msg, xfer); | ||
575 | |||
576 | if (msg->status != -EINPROGRESS) | ||
577 | goto out; | ||
578 | |||
579 | if (xfer->delay_usecs) | ||
580 | udelay(xfer->delay_usecs); | ||
581 | |||
582 | if (xfer->cs_change) { | ||
583 | if (list_is_last(&xfer->transfer_list, | ||
584 | &msg->transfers)) { | ||
585 | keep_cs = true; | ||
586 | } else { | ||
587 | cur_cs = !cur_cs; | ||
588 | spi_set_cs(msg->spi, cur_cs); | ||
589 | } | ||
590 | } | ||
591 | |||
592 | msg->actual_length += xfer->len; | ||
593 | } | ||
594 | |||
595 | out: | ||
596 | if (ret != 0 || !keep_cs) | ||
597 | spi_set_cs(msg->spi, false); | ||
598 | |||
599 | if (msg->status == -EINPROGRESS) | ||
600 | msg->status = ret; | ||
601 | |||
602 | spi_finalize_current_message(master); | ||
603 | |||
604 | return ret; | ||
605 | } | ||
606 | |||
607 | /** | ||
608 | * spi_finalize_current_transfer - report completion of a transfer | ||
609 | * | ||
610 | * Called by SPI drivers using the core transfer_one_message() | ||
611 | * implementation to notify it that the current interrupt driven | ||
612 | * transfer has finised and the next one may be scheduled. | ||
613 | */ | ||
614 | void spi_finalize_current_transfer(struct spi_master *master) | ||
615 | { | ||
616 | complete(&master->xfer_completion); | ||
617 | } | ||
618 | EXPORT_SYMBOL_GPL(spi_finalize_current_transfer); | ||
619 | |||
528 | /** | 620 | /** |
529 | * spi_pump_messages - kthread work function which processes spi message queue | 621 | * spi_pump_messages - kthread work function which processes spi message queue |
530 | * @work: pointer to kthread work struct contained in the master struct | 622 | * @work: pointer to kthread work struct contained in the master struct |
@@ -559,6 +651,7 @@ static void spi_pump_messages(struct kthread_work *work) | |||
559 | pm_runtime_mark_last_busy(master->dev.parent); | 651 | pm_runtime_mark_last_busy(master->dev.parent); |
560 | pm_runtime_put_autosuspend(master->dev.parent); | 652 | pm_runtime_put_autosuspend(master->dev.parent); |
561 | } | 653 | } |
654 | trace_spi_master_idle(master); | ||
562 | return; | 655 | return; |
563 | } | 656 | } |
564 | 657 | ||
@@ -587,6 +680,9 @@ static void spi_pump_messages(struct kthread_work *work) | |||
587 | } | 680 | } |
588 | } | 681 | } |
589 | 682 | ||
683 | if (!was_busy) | ||
684 | trace_spi_master_busy(master); | ||
685 | |||
590 | if (!was_busy && master->prepare_transfer_hardware) { | 686 | if (!was_busy && master->prepare_transfer_hardware) { |
591 | ret = master->prepare_transfer_hardware(master); | 687 | ret = master->prepare_transfer_hardware(master); |
592 | if (ret) { | 688 | if (ret) { |
@@ -599,6 +695,20 @@ static void spi_pump_messages(struct kthread_work *work) | |||
599 | } | 695 | } |
600 | } | 696 | } |
601 | 697 | ||
698 | trace_spi_message_start(master->cur_msg); | ||
699 | |||
700 | if (master->prepare_message) { | ||
701 | ret = master->prepare_message(master, master->cur_msg); | ||
702 | if (ret) { | ||
703 | dev_err(&master->dev, | ||
704 | "failed to prepare message: %d\n", ret); | ||
705 | master->cur_msg->status = ret; | ||
706 | spi_finalize_current_message(master); | ||
707 | return; | ||
708 | } | ||
709 | master->cur_msg_prepared = true; | ||
710 | } | ||
711 | |||
602 | ret = master->transfer_one_message(master, master->cur_msg); | 712 | ret = master->transfer_one_message(master, master->cur_msg); |
603 | if (ret) { | 713 | if (ret) { |
604 | dev_err(&master->dev, | 714 | dev_err(&master->dev, |
@@ -680,6 +790,7 @@ void spi_finalize_current_message(struct spi_master *master) | |||
680 | { | 790 | { |
681 | struct spi_message *mesg; | 791 | struct spi_message *mesg; |
682 | unsigned long flags; | 792 | unsigned long flags; |
793 | int ret; | ||
683 | 794 | ||
684 | spin_lock_irqsave(&master->queue_lock, flags); | 795 | spin_lock_irqsave(&master->queue_lock, flags); |
685 | mesg = master->cur_msg; | 796 | mesg = master->cur_msg; |
@@ -688,9 +799,20 @@ void spi_finalize_current_message(struct spi_master *master) | |||
688 | queue_kthread_work(&master->kworker, &master->pump_messages); | 799 | queue_kthread_work(&master->kworker, &master->pump_messages); |
689 | spin_unlock_irqrestore(&master->queue_lock, flags); | 800 | spin_unlock_irqrestore(&master->queue_lock, flags); |
690 | 801 | ||
802 | if (master->cur_msg_prepared && master->unprepare_message) { | ||
803 | ret = master->unprepare_message(master, mesg); | ||
804 | if (ret) { | ||
805 | dev_err(&master->dev, | ||
806 | "failed to unprepare message: %d\n", ret); | ||
807 | } | ||
808 | } | ||
809 | master->cur_msg_prepared = false; | ||
810 | |||
691 | mesg->state = NULL; | 811 | mesg->state = NULL; |
692 | if (mesg->complete) | 812 | if (mesg->complete) |
693 | mesg->complete(mesg->context); | 813 | mesg->complete(mesg->context); |
814 | |||
815 | trace_spi_message_done(mesg); | ||
694 | } | 816 | } |
695 | EXPORT_SYMBOL_GPL(spi_finalize_current_message); | 817 | EXPORT_SYMBOL_GPL(spi_finalize_current_message); |
696 | 818 | ||
@@ -805,6 +927,8 @@ static int spi_master_initialize_queue(struct spi_master *master) | |||
805 | 927 | ||
806 | master->queued = true; | 928 | master->queued = true; |
807 | master->transfer = spi_queued_transfer; | 929 | master->transfer = spi_queued_transfer; |
930 | if (!master->transfer_one_message) | ||
931 | master->transfer_one_message = spi_transfer_one_message; | ||
808 | 932 | ||
809 | /* Initialize and start queue */ | 933 | /* Initialize and start queue */ |
810 | ret = spi_init_queue(master); | 934 | ret = spi_init_queue(master); |
@@ -1205,6 +1329,7 @@ int spi_register_master(struct spi_master *master) | |||
1205 | spin_lock_init(&master->bus_lock_spinlock); | 1329 | spin_lock_init(&master->bus_lock_spinlock); |
1206 | mutex_init(&master->bus_lock_mutex); | 1330 | mutex_init(&master->bus_lock_mutex); |
1207 | master->bus_lock_flag = 0; | 1331 | master->bus_lock_flag = 0; |
1332 | init_completion(&master->xfer_completion); | ||
1208 | 1333 | ||
1209 | /* register the device, then userspace will see it. | 1334 | /* register the device, then userspace will see it. |
1210 | * registration fails if the bus ID is in use. | 1335 | * registration fails if the bus ID is in use. |
@@ -1451,6 +1576,10 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1451 | struct spi_master *master = spi->master; | 1576 | struct spi_master *master = spi->master; |
1452 | struct spi_transfer *xfer; | 1577 | struct spi_transfer *xfer; |
1453 | 1578 | ||
1579 | message->spi = spi; | ||
1580 | |||
1581 | trace_spi_message_submit(message); | ||
1582 | |||
1454 | if (list_empty(&message->transfers)) | 1583 | if (list_empty(&message->transfers)) |
1455 | return -EINVAL; | 1584 | return -EINVAL; |
1456 | if (!message->complete) | 1585 | if (!message->complete) |
@@ -1550,7 +1679,6 @@ static int __spi_async(struct spi_device *spi, struct spi_message *message) | |||
1550 | } | 1679 | } |
1551 | } | 1680 | } |
1552 | 1681 | ||
1553 | message->spi = spi; | ||
1554 | message->status = -EINPROGRESS; | 1682 | message->status = -EINPROGRESS; |
1555 | return master->transfer(spi, message); | 1683 | return master->transfer(spi, message); |
1556 | } | 1684 | } |
diff --git a/include/linux/spi/spi.h b/include/linux/spi/spi.h index 4d634d66ba0b..1619ed48e75d 100644 --- a/include/linux/spi/spi.h +++ b/include/linux/spi/spi.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/mod_devicetable.h> | 23 | #include <linux/mod_devicetable.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/kthread.h> | 25 | #include <linux/kthread.h> |
26 | #include <linux/completion.h> | ||
26 | 27 | ||
27 | /* | 28 | /* |
28 | * INTERFACES between SPI master-side drivers and SPI infrastructure. | 29 | * INTERFACES between SPI master-side drivers and SPI infrastructure. |
@@ -150,8 +151,7 @@ static inline void *spi_get_drvdata(struct spi_device *spi) | |||
150 | } | 151 | } |
151 | 152 | ||
152 | struct spi_message; | 153 | struct spi_message; |
153 | 154 | struct spi_transfer; | |
154 | |||
155 | 155 | ||
156 | /** | 156 | /** |
157 | * struct spi_driver - Host side "protocol" driver | 157 | * struct spi_driver - Host side "protocol" driver |
@@ -257,6 +257,9 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) | |||
257 | * @queue_lock: spinlock to syncronise access to message queue | 257 | * @queue_lock: spinlock to syncronise access to message queue |
258 | * @queue: message queue | 258 | * @queue: message queue |
259 | * @cur_msg: the currently in-flight message | 259 | * @cur_msg: the currently in-flight message |
260 | * @cur_msg_prepared: spi_prepare_message was called for the currently | ||
261 | * in-flight message | ||
262 | * @xfer_completion: used by core tranfer_one_message() | ||
260 | * @busy: message pump is busy | 263 | * @busy: message pump is busy |
261 | * @running: message pump is running | 264 | * @running: message pump is running |
262 | * @rt: whether this queue is set to run as a realtime task | 265 | * @rt: whether this queue is set to run as a realtime task |
@@ -274,6 +277,16 @@ static inline void spi_unregister_driver(struct spi_driver *sdrv) | |||
274 | * @unprepare_transfer_hardware: there are currently no more messages on the | 277 | * @unprepare_transfer_hardware: there are currently no more messages on the |
275 | * queue so the subsystem notifies the driver that it may relax the | 278 | * queue so the subsystem notifies the driver that it may relax the |
276 | * hardware by issuing this call | 279 | * hardware by issuing this call |
280 | * @set_cs: assert or deassert chip select, true to assert. May be called | ||
281 | * from interrupt context. | ||
282 | * @prepare_message: set up the controller to transfer a single message, | ||
283 | * for example doing DMA mapping. Called from threaded | ||
284 | * context. | ||
285 | * @transfer_one: transfer a single spi_transfer. When the | ||
286 | * driver is finished with this transfer it must call | ||
287 | * spi_finalize_current_transfer() so the subsystem can issue | ||
288 | * the next transfer | ||
289 | * @unprepare_message: undo any work done by prepare_message(). | ||
277 | * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS | 290 | * @cs_gpios: Array of GPIOs to use as chip select lines; one per CS |
278 | * number. Any individual value may be -ENOENT for CS lines that | 291 | * number. Any individual value may be -ENOENT for CS lines that |
279 | * are not GPIOs (driven by the SPI controller itself). | 292 | * are not GPIOs (driven by the SPI controller itself). |
@@ -388,11 +401,25 @@ struct spi_master { | |||
388 | bool running; | 401 | bool running; |
389 | bool rt; | 402 | bool rt; |
390 | bool auto_runtime_pm; | 403 | bool auto_runtime_pm; |
404 | bool cur_msg_prepared; | ||
405 | struct completion xfer_completion; | ||
391 | 406 | ||
392 | int (*prepare_transfer_hardware)(struct spi_master *master); | 407 | int (*prepare_transfer_hardware)(struct spi_master *master); |
393 | int (*transfer_one_message)(struct spi_master *master, | 408 | int (*transfer_one_message)(struct spi_master *master, |
394 | struct spi_message *mesg); | 409 | struct spi_message *mesg); |
395 | int (*unprepare_transfer_hardware)(struct spi_master *master); | 410 | int (*unprepare_transfer_hardware)(struct spi_master *master); |
411 | int (*prepare_message)(struct spi_master *master, | ||
412 | struct spi_message *message); | ||
413 | int (*unprepare_message)(struct spi_master *master, | ||
414 | struct spi_message *message); | ||
415 | |||
416 | /* | ||
417 | * These hooks are for drivers that use a generic implementation | ||
418 | * of transfer_one_message() provied by the core. | ||
419 | */ | ||
420 | void (*set_cs)(struct spi_device *spi, bool enable); | ||
421 | int (*transfer_one)(struct spi_master *master, struct spi_device *spi, | ||
422 | struct spi_transfer *transfer); | ||
396 | 423 | ||
397 | /* gpio chip select */ | 424 | /* gpio chip select */ |
398 | int *cs_gpios; | 425 | int *cs_gpios; |
@@ -428,6 +455,7 @@ extern int spi_master_resume(struct spi_master *master); | |||
428 | /* Calls the driver make to interact with the message queue */ | 455 | /* Calls the driver make to interact with the message queue */ |
429 | extern struct spi_message *spi_get_next_queued_message(struct spi_master *master); | 456 | extern struct spi_message *spi_get_next_queued_message(struct spi_master *master); |
430 | extern void spi_finalize_current_message(struct spi_master *master); | 457 | extern void spi_finalize_current_message(struct spi_master *master); |
458 | extern void spi_finalize_current_transfer(struct spi_master *master); | ||
431 | 459 | ||
432 | /* the spi driver core manages memory for the spi_master classdev */ | 460 | /* the spi driver core manages memory for the spi_master classdev */ |
433 | extern struct spi_master * | 461 | extern struct spi_master * |
diff --git a/include/trace/events/spi.h b/include/trace/events/spi.h new file mode 100644 index 000000000000..7e02c983bbe2 --- /dev/null +++ b/include/trace/events/spi.h | |||
@@ -0,0 +1,156 @@ | |||
1 | #undef TRACE_SYSTEM | ||
2 | #define TRACE_SYSTEM spi | ||
3 | |||
4 | #if !defined(_TRACE_SPI_H) || defined(TRACE_HEADER_MULTI_READ) | ||
5 | #define _TRACE_SPI_H | ||
6 | |||
7 | #include <linux/ktime.h> | ||
8 | #include <linux/tracepoint.h> | ||
9 | |||
10 | DECLARE_EVENT_CLASS(spi_master, | ||
11 | |||
12 | TP_PROTO(struct spi_master *master), | ||
13 | |||
14 | TP_ARGS(master), | ||
15 | |||
16 | TP_STRUCT__entry( | ||
17 | __field( int, bus_num ) | ||
18 | ), | ||
19 | |||
20 | TP_fast_assign( | ||
21 | __entry->bus_num = master->bus_num; | ||
22 | ), | ||
23 | |||
24 | TP_printk("spi%d", (int)__entry->bus_num) | ||
25 | |||
26 | ); | ||
27 | |||
28 | DEFINE_EVENT(spi_master, spi_master_idle, | ||
29 | |||
30 | TP_PROTO(struct spi_master *master), | ||
31 | |||
32 | TP_ARGS(master) | ||
33 | |||
34 | ); | ||
35 | |||
36 | DEFINE_EVENT(spi_master, spi_master_busy, | ||
37 | |||
38 | TP_PROTO(struct spi_master *master), | ||
39 | |||
40 | TP_ARGS(master) | ||
41 | |||
42 | ); | ||
43 | |||
44 | DECLARE_EVENT_CLASS(spi_message, | ||
45 | |||
46 | TP_PROTO(struct spi_message *msg), | ||
47 | |||
48 | TP_ARGS(msg), | ||
49 | |||
50 | TP_STRUCT__entry( | ||
51 | __field( int, bus_num ) | ||
52 | __field( int, chip_select ) | ||
53 | __field( struct spi_message *, msg ) | ||
54 | ), | ||
55 | |||
56 | TP_fast_assign( | ||
57 | __entry->bus_num = msg->spi->master->bus_num; | ||
58 | __entry->chip_select = msg->spi->chip_select; | ||
59 | __entry->msg = msg; | ||
60 | ), | ||
61 | |||
62 | TP_printk("spi%d.%d %p", (int)__entry->bus_num, | ||
63 | (int)__entry->chip_select, | ||
64 | (struct spi_message *)__entry->msg) | ||
65 | ); | ||
66 | |||
67 | DEFINE_EVENT(spi_message, spi_message_submit, | ||
68 | |||
69 | TP_PROTO(struct spi_message *msg), | ||
70 | |||
71 | TP_ARGS(msg) | ||
72 | |||
73 | ); | ||
74 | |||
75 | DEFINE_EVENT(spi_message, spi_message_start, | ||
76 | |||
77 | TP_PROTO(struct spi_message *msg), | ||
78 | |||
79 | TP_ARGS(msg) | ||
80 | |||
81 | ); | ||
82 | |||
83 | TRACE_EVENT(spi_message_done, | ||
84 | |||
85 | TP_PROTO(struct spi_message *msg), | ||
86 | |||
87 | TP_ARGS(msg), | ||
88 | |||
89 | TP_STRUCT__entry( | ||
90 | __field( int, bus_num ) | ||
91 | __field( int, chip_select ) | ||
92 | __field( struct spi_message *, msg ) | ||
93 | __field( unsigned, frame ) | ||
94 | __field( unsigned, actual ) | ||
95 | ), | ||
96 | |||
97 | TP_fast_assign( | ||
98 | __entry->bus_num = msg->spi->master->bus_num; | ||
99 | __entry->chip_select = msg->spi->chip_select; | ||
100 | __entry->msg = msg; | ||
101 | __entry->frame = msg->frame_length; | ||
102 | __entry->actual = msg->actual_length; | ||
103 | ), | ||
104 | |||
105 | TP_printk("spi%d.%d %p len=%u/%u", (int)__entry->bus_num, | ||
106 | (int)__entry->chip_select, | ||
107 | (struct spi_message *)__entry->msg, | ||
108 | (unsigned)__entry->actual, (unsigned)__entry->frame) | ||
109 | ); | ||
110 | |||
111 | DECLARE_EVENT_CLASS(spi_transfer, | ||
112 | |||
113 | TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer), | ||
114 | |||
115 | TP_ARGS(msg, xfer), | ||
116 | |||
117 | TP_STRUCT__entry( | ||
118 | __field( int, bus_num ) | ||
119 | __field( int, chip_select ) | ||
120 | __field( struct spi_transfer *, xfer ) | ||
121 | __field( int, len ) | ||
122 | ), | ||
123 | |||
124 | TP_fast_assign( | ||
125 | __entry->bus_num = msg->spi->master->bus_num; | ||
126 | __entry->chip_select = msg->spi->chip_select; | ||
127 | __entry->xfer = xfer; | ||
128 | __entry->len = xfer->len; | ||
129 | ), | ||
130 | |||
131 | TP_printk("spi%d.%d %p len=%d", (int)__entry->bus_num, | ||
132 | (int)__entry->chip_select, | ||
133 | (struct spi_message *)__entry->xfer, | ||
134 | (int)__entry->len) | ||
135 | ); | ||
136 | |||
137 | DEFINE_EVENT(spi_transfer, spi_transfer_start, | ||
138 | |||
139 | TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer), | ||
140 | |||
141 | TP_ARGS(msg, xfer) | ||
142 | |||
143 | ); | ||
144 | |||
145 | DEFINE_EVENT(spi_transfer, spi_transfer_stop, | ||
146 | |||
147 | TP_PROTO(struct spi_message *msg, struct spi_transfer *xfer), | ||
148 | |||
149 | TP_ARGS(msg, xfer) | ||
150 | |||
151 | ); | ||
152 | |||
153 | #endif /* _TRACE_POWER_H */ | ||
154 | |||
155 | /* This part must be outside protection */ | ||
156 | #include <trace/define_trace.h> | ||