diff options
-rw-r--r-- | arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | 2 | ||||
-rw-r--r-- | drivers/spi/spi-s3c64xx.c | 31 |
2 files changed, 26 insertions, 7 deletions
diff --git a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h index c818a7c18929..ceba18d23a5a 100644 --- a/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h +++ b/arch/arm/plat-samsung/include/plat/s3c64xx-spi.h | |||
@@ -18,7 +18,6 @@ struct platform_device; | |||
18 | * @fb_delay: Slave specific feedback delay. | 18 | * @fb_delay: Slave specific feedback delay. |
19 | * Refer to FB_CLK_SEL register definition in SPI chapter. | 19 | * Refer to FB_CLK_SEL register definition in SPI chapter. |
20 | * @line: Custom 'identity' of the CS line. | 20 | * @line: Custom 'identity' of the CS line. |
21 | * @set_level: CS line control. | ||
22 | * | 21 | * |
23 | * This is per SPI-Slave Chipselect information. | 22 | * This is per SPI-Slave Chipselect information. |
24 | * Allocate and initialize one in machine init code and make the | 23 | * Allocate and initialize one in machine init code and make the |
@@ -27,7 +26,6 @@ struct platform_device; | |||
27 | struct s3c64xx_spi_csinfo { | 26 | struct s3c64xx_spi_csinfo { |
28 | u8 fb_delay; | 27 | u8 fb_delay; |
29 | unsigned line; | 28 | unsigned line; |
30 | void (*set_level)(unsigned line_id, int lvl); | ||
31 | }; | 29 | }; |
32 | 30 | ||
33 | /** | 31 | /** |
diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 0a9e43e635aa..e4182ea2f306 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
29 | #include <linux/spi/spi.h> | 29 | #include <linux/spi/spi.h> |
30 | #include <linux/gpio.h> | ||
30 | 31 | ||
31 | #include <mach/dma.h> | 32 | #include <mach/dma.h> |
32 | #include <plat/s3c64xx-spi.h> | 33 | #include <plat/s3c64xx-spi.h> |
@@ -411,14 +412,14 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd, | |||
411 | if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ | 412 | if (sdd->tgl_spi != spi) { /* if last mssg on diff device */ |
412 | /* Deselect the last toggled device */ | 413 | /* Deselect the last toggled device */ |
413 | cs = sdd->tgl_spi->controller_data; | 414 | cs = sdd->tgl_spi->controller_data; |
414 | cs->set_level(cs->line, | 415 | gpio_set_value(cs->line, |
415 | spi->mode & SPI_CS_HIGH ? 0 : 1); | 416 | spi->mode & SPI_CS_HIGH ? 0 : 1); |
416 | } | 417 | } |
417 | sdd->tgl_spi = NULL; | 418 | sdd->tgl_spi = NULL; |
418 | } | 419 | } |
419 | 420 | ||
420 | cs = spi->controller_data; | 421 | cs = spi->controller_data; |
421 | cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); | 422 | gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0); |
422 | } | 423 | } |
423 | 424 | ||
424 | static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, | 425 | static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd, |
@@ -504,7 +505,7 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd, | |||
504 | if (sdd->tgl_spi == spi) | 505 | if (sdd->tgl_spi == spi) |
505 | sdd->tgl_spi = NULL; | 506 | sdd->tgl_spi = NULL; |
506 | 507 | ||
507 | cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); | 508 | gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1); |
508 | } | 509 | } |
509 | 510 | ||
510 | static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) | 511 | static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) |
@@ -833,11 +834,21 @@ static int s3c64xx_spi_setup(struct spi_device *spi) | |||
833 | unsigned long flags; | 834 | unsigned long flags; |
834 | int err = 0; | 835 | int err = 0; |
835 | 836 | ||
836 | if (cs == NULL || cs->set_level == NULL) { | 837 | if (cs == NULL) { |
837 | dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select); | 838 | dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select); |
838 | return -ENODEV; | 839 | return -ENODEV; |
839 | } | 840 | } |
840 | 841 | ||
842 | if (!spi_get_ctldata(spi)) { | ||
843 | err = gpio_request(cs->line, dev_name(&spi->dev)); | ||
844 | if (err) { | ||
845 | dev_err(&spi->dev, "request for slave select gpio " | ||
846 | "line [%d] failed\n", cs->line); | ||
847 | return -EBUSY; | ||
848 | } | ||
849 | spi_set_ctldata(spi, cs); | ||
850 | } | ||
851 | |||
841 | sdd = spi_master_get_devdata(spi->master); | 852 | sdd = spi_master_get_devdata(spi->master); |
842 | sci = sdd->cntrlr_info; | 853 | sci = sdd->cntrlr_info; |
843 | 854 | ||
@@ -908,6 +919,15 @@ setup_exit: | |||
908 | return err; | 919 | return err; |
909 | } | 920 | } |
910 | 921 | ||
922 | static void s3c64xx_spi_cleanup(struct spi_device *spi) | ||
923 | { | ||
924 | struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi); | ||
925 | |||
926 | if (cs) | ||
927 | gpio_free(cs->line); | ||
928 | spi_set_ctldata(spi, NULL); | ||
929 | } | ||
930 | |||
911 | static irqreturn_t s3c64xx_spi_irq(int irq, void *data) | 931 | static irqreturn_t s3c64xx_spi_irq(int irq, void *data) |
912 | { | 932 | { |
913 | struct s3c64xx_spi_driver_data *sdd = data; | 933 | struct s3c64xx_spi_driver_data *sdd = data; |
@@ -1049,6 +1069,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev) | |||
1049 | 1069 | ||
1050 | master->bus_num = sdd->port_id; | 1070 | master->bus_num = sdd->port_id; |
1051 | master->setup = s3c64xx_spi_setup; | 1071 | master->setup = s3c64xx_spi_setup; |
1072 | master->cleanup = s3c64xx_spi_cleanup; | ||
1052 | master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; | 1073 | master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer; |
1053 | master->transfer_one_message = s3c64xx_spi_transfer_one_message; | 1074 | master->transfer_one_message = s3c64xx_spi_transfer_one_message; |
1054 | master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; | 1075 | master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer; |