diff options
Diffstat (limited to 'drivers/spi/spi-s3c64xx.c')
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 264 |
1 files changed, 128 insertions, 136 deletions
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 512b8893893b..4c4b0a1219a7 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 | reinit_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,11 +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: |
1102 | pm_runtime_put(&sdd->pdev->dev); | ||
1124 | /* 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); | ||
1125 | disable_cs(sdd, spi); | 1105 | disable_cs(sdd, spi); |
1126 | 1106 | ||
1127 | gpio_free(cs->line); | 1107 | gpio_free(cs->line); |
@@ -1140,8 +1120,8 @@ static void s3c64xx_spi_cleanup(struct spi_device *spi) | |||
1140 | struct s3c64xx_spi_driver_data *sdd; | 1120 | struct s3c64xx_spi_driver_data *sdd; |
1141 | 1121 | ||
1142 | sdd = spi_master_get_devdata(spi->master); | 1122 | sdd = spi_master_get_devdata(spi->master); |
1143 | if (cs && sdd->cs_gpio) { | 1123 | if (spi->cs_gpio) { |
1144 | gpio_free(cs->line); | 1124 | gpio_free(spi->cs_gpio); |
1145 | if (spi->dev.of_node) | 1125 | if (spi->dev.of_node) |
1146 | kfree(cs); | 1126 | kfree(cs); |
1147 | } | 1127 | } |
@@ -1359,7 +1339,9 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) | |||
1359 | master->setup = s3c64xx_spi_setup; | 1339 | master->setup = s3c64xx_spi_setup; |
1360 | master->cleanup = s3c64xx_spi_cleanup; | 1340 | master->cleanup = s3c64xx_spi_cleanup; |
1361 | master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; | 1341 | master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; |
1362 | 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; | ||
1363 | master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; | 1345 | master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; |
1364 | master->num_chipselect = sci->num_cs; | 1346 | master->num_chipselect = sci->num_cs; |
1365 | master->dma_alignment = 8; | 1347 | master->dma_alignment = 8; |
@@ -1428,9 +1410,12 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) | |||
1428 | S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, | 1410 | S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, |
1429 | sdd->regs + S3C64XX_SPI_INT_EN); | 1411 | sdd->regs + S3C64XX_SPI_INT_EN); |
1430 | 1412 | ||
1431 | if (spi_register_master(master)) { | 1413 | pm_runtime_set_active(&pdev->dev); |
1432 | dev_err(&pdev->dev, "cannot register SPI master\n"); | 1414 | pm_runtime_enable(&pdev->dev); |
1433 | ret = -EBUSY; | 1415 | |
1416 | ret = devm_spi_register_master(&pdev->dev, master); | ||
1417 | if (ret != 0) { | ||
1418 | dev_err(&pdev->dev, "cannot register SPI master: %d\n", ret); | ||
1434 | goto err3; | 1419 | goto err3; |
1435 | } | 1420 | } |
1436 | 1421 | ||
@@ -1440,8 +1425,6 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) | |||
1440 | mem_res, | 1425 | mem_res, |
1441 | sdd->rx_dma.dmach, sdd->tx_dma.dmach); | 1426 | sdd->rx_dma.dmach, sdd->tx_dma.dmach); |
1442 | 1427 | ||
1443 | pm_runtime_enable(&pdev->dev); | ||
1444 | |||
1445 | return 0; | 1428 | return 0; |
1446 | 1429 | ||
1447 | err3: | 1430 | err3: |
@@ -1461,16 +1444,12 @@ static int s3c64xx_spi_remove(struct platform_device *pdev) | |||
1461 | 1444 | ||
1462 | pm_runtime_disable(&pdev->dev); | 1445 | pm_runtime_disable(&pdev->dev); |
1463 | 1446 | ||
1464 | spi_unregister_master(master); | ||
1465 | |||
1466 | writel(0, sdd->regs + S3C64XX_SPI_INT_EN); | 1447 | writel(0, sdd->regs + S3C64XX_SPI_INT_EN); |
1467 | 1448 | ||
1468 | clk_disable_unprepare(sdd->src_clk); | 1449 | clk_disable_unprepare(sdd->src_clk); |
1469 | 1450 | ||
1470 | clk_disable_unprepare(sdd->clk); | 1451 | clk_disable_unprepare(sdd->clk); |
1471 | 1452 | ||
1472 | spi_master_put(master); | ||
1473 | |||
1474 | return 0; | 1453 | return 0; |
1475 | } | 1454 | } |
1476 | 1455 | ||
@@ -1480,11 +1459,14 @@ static int s3c64xx_spi_suspend(struct device *dev) | |||
1480 | struct spi_master *master = dev_get_drvdata(dev); | 1459 | struct spi_master *master = dev_get_drvdata(dev); |
1481 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | 1460 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
1482 | 1461 | ||
1483 | spi_master_suspend(master); | 1462 | int ret = spi_master_suspend(master); |
1463 | if (ret) | ||
1464 | return ret; | ||
1484 | 1465 | ||
1485 | /* Disable the clock */ | 1466 | if (!pm_runtime_suspended(dev)) { |
1486 | clk_disable_unprepare(sdd->src_clk); | 1467 | clk_disable_unprepare(sdd->clk); |
1487 | clk_disable_unprepare(sdd->clk); | 1468 | clk_disable_unprepare(sdd->src_clk); |
1469 | } | ||
1488 | 1470 | ||
1489 | sdd->cur_speed = 0; /* Output Clock is stopped */ | 1471 | sdd->cur_speed = 0; /* Output Clock is stopped */ |
1490 | 1472 | ||
@@ -1500,15 +1482,14 @@ static int s3c64xx_spi_resume(struct device *dev) | |||
1500 | if (sci->cfg_gpio) | 1482 | if (sci->cfg_gpio) |
1501 | sci->cfg_gpio(); | 1483 | sci->cfg_gpio(); |
1502 | 1484 | ||
1503 | /* Enable the clock */ | 1485 | if (!pm_runtime_suspended(dev)) { |
1504 | clk_prepare_enable(sdd->src_clk); | 1486 | clk_prepare_enable(sdd->src_clk); |
1505 | clk_prepare_enable(sdd->clk); | 1487 | clk_prepare_enable(sdd->clk); |
1488 | } | ||
1506 | 1489 | ||
1507 | s3c64xx_spi_hwinit(sdd, sdd->port_id); | 1490 | s3c64xx_spi_hwinit(sdd, sdd->port_id); |
1508 | 1491 | ||
1509 | spi_master_resume(master); | 1492 | return spi_master_resume(master); |
1510 | |||
1511 | return 0; | ||
1512 | } | 1493 | } |
1513 | #endif /* CONFIG_PM_SLEEP */ | 1494 | #endif /* CONFIG_PM_SLEEP */ |
1514 | 1495 | ||
@@ -1528,9 +1509,17 @@ static int s3c64xx_spi_runtime_resume(struct device *dev) | |||
1528 | { | 1509 | { |
1529 | struct spi_master *master = dev_get_drvdata(dev); | 1510 | struct spi_master *master = dev_get_drvdata(dev); |
1530 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); | 1511 | struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master); |
1512 | int ret; | ||
1531 | 1513 | ||
1532 | clk_prepare_enable(sdd->src_clk); | 1514 | ret = clk_prepare_enable(sdd->src_clk); |
1533 | clk_prepare_enable(sdd->clk); | 1515 | if (ret != 0) |
1516 | return ret; | ||
1517 | |||
1518 | ret = clk_prepare_enable(sdd->clk); | ||
1519 | if (ret != 0) { | ||
1520 | clk_disable_unprepare(sdd->src_clk); | ||
1521 | return ret; | ||
1522 | } | ||
1534 | 1523 | ||
1535 | return 0; | 1524 | return 0; |
1536 | } | 1525 | } |
@@ -1616,6 +1605,18 @@ static struct platform_device_id s3c64xx_spi_driver_ids[] = { | |||
1616 | }; | 1605 | }; |
1617 | 1606 | ||
1618 | static const struct of_device_id s3c64xx_spi_dt_match[] = { | 1607 | static const struct of_device_id s3c64xx_spi_dt_match[] = { |
1608 | { .compatible = "samsung,s3c2443-spi", | ||
1609 | .data = (void *)&s3c2443_spi_port_config, | ||
1610 | }, | ||
1611 | { .compatible = "samsung,s3c6410-spi", | ||
1612 | .data = (void *)&s3c6410_spi_port_config, | ||
1613 | }, | ||
1614 | { .compatible = "samsung,s5pc100-spi", | ||
1615 | .data = (void *)&s5pc100_spi_port_config, | ||
1616 | }, | ||
1617 | { .compatible = "samsung,s5pv210-spi", | ||
1618 | .data = (void *)&s5pv210_spi_port_config, | ||
1619 | }, | ||
1619 | { .compatible = "samsung,exynos4210-spi", | 1620 | { .compatible = "samsung,exynos4210-spi", |
1620 | .data = (void *)&exynos4_spi_port_config, | 1621 | .data = (void *)&exynos4_spi_port_config, |
1621 | }, | 1622 | }, |
@@ -1633,22 +1634,13 @@ static struct platform_driver s3c64xx_spi_driver = { | |||
1633 | .pm = &s3c64xx_spi_pm, | 1634 | .pm = &s3c64xx_spi_pm, |
1634 | .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), | 1635 | .of_match_table = of_match_ptr(s3c64xx_spi_dt_match), |
1635 | }, | 1636 | }, |
1637 | .probe = s3c64xx_spi_probe, | ||
1636 | .remove = s3c64xx_spi_remove, | 1638 | .remove = s3c64xx_spi_remove, |
1637 | .id_table = s3c64xx_spi_driver_ids, | 1639 | .id_table = s3c64xx_spi_driver_ids, |
1638 | }; | 1640 | }; |
1639 | MODULE_ALIAS("platform:s3c64xx-spi"); | 1641 | MODULE_ALIAS("platform:s3c64xx-spi"); |
1640 | 1642 | ||
1641 | static int __init s3c64xx_spi_init(void) | 1643 | module_platform_driver(s3c64xx_spi_driver); |
1642 | { | ||
1643 | return platform_driver_probe(&s3c64xx_spi_driver, s3c64xx_spi_probe); | ||
1644 | } | ||
1645 | subsys_initcall(s3c64xx_spi_init); | ||
1646 | |||
1647 | static void __exit s3c64xx_spi_exit(void) | ||
1648 | { | ||
1649 | platform_driver_unregister(&s3c64xx_spi_driver); | ||
1650 | } | ||
1651 | module_exit(s3c64xx_spi_exit); | ||
1652 | 1644 | ||
1653 | MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); | 1645 | MODULE_AUTHOR("Jaswinder Singh <jassi.brar@samsung.com>"); |
1654 | MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); | 1646 | MODULE_DESCRIPTION("S3C64XX SPI Controller Driver"); |