diff options
author | Mark Brown <broonie@linaro.org> | 2013-10-05 07:23:38 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-10-17 05:57:47 -0400 |
commit | 63fc184cde2d771affc2e7885c05a2792bae9f86 (patch) | |
tree | 2876e182ab6c39159dff711d30ac551fac369527 /drivers/spi/spi-tegra20-slink.c | |
parent | 3cb7b407ce84e5756076f64bf4341cc101955966 (diff) |
spi/tegra20-slink: Crude refactoring to use core message parsing
This is a half done conversion with minimal code reorganisation provided
for bisection purposes. A further patch will move the first transfer
preparation into tegra_slink_prepare_message().
The cs_change and udelay handling is removed, these should be
implemented by the framework and in any case are buggy - the two fields
should not be related and the cs_change handling appears to at best only
work the first time it's used in a message.
Signed-off-by: Mark Brown <broonie@linaro.org>
Tested-by: Stephen Warren <swarren@nvidia.com>
Diffstat (limited to 'drivers/spi/spi-tegra20-slink.c')
-rw-r--r-- | drivers/spi/spi-tegra20-slink.c | 88 |
1 files changed, 46 insertions, 42 deletions
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c index d1d2bff01301..3576fcb3f79b 100644 --- a/drivers/spi/spi-tegra20-slink.c +++ b/drivers/spi/spi-tegra20-slink.c | |||
@@ -196,6 +196,7 @@ struct tegra_slink_data { | |||
196 | u32 rx_status; | 196 | u32 rx_status; |
197 | u32 status_reg; | 197 | u32 status_reg; |
198 | bool is_packed; | 198 | bool is_packed; |
199 | bool is_first_msg; | ||
199 | unsigned long packed_size; | 200 | unsigned long packed_size; |
200 | 201 | ||
201 | u32 command_reg; | 202 | u32 command_reg; |
@@ -823,55 +824,56 @@ static int tegra_slink_setup(struct spi_device *spi) | |||
823 | return 0; | 824 | return 0; |
824 | } | 825 | } |
825 | 826 | ||
826 | static int tegra_slink_transfer_one_message(struct spi_master *master, | 827 | static int tegra_slink_prepare_message(struct spi_master *master, |
827 | struct spi_message *msg) | 828 | struct spi_message *msg) |
828 | { | 829 | { |
829 | bool is_first_msg = true; | ||
830 | struct tegra_slink_data *tspi = spi_master_get_devdata(master); | 830 | struct tegra_slink_data *tspi = spi_master_get_devdata(master); |
831 | struct spi_transfer *xfer; | ||
832 | struct spi_device *spi = msg->spi; | ||
833 | int ret; | ||
834 | 831 | ||
835 | msg->status = 0; | 832 | tspi->is_first_msg = true; |
836 | msg->actual_length = 0; | ||
837 | 833 | ||
838 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { | 834 | return 0; |
839 | INIT_COMPLETION(tspi->xfer_completion); | 835 | } |
840 | ret = tegra_slink_start_transfer_one(spi, xfer, is_first_msg); | ||
841 | if (ret < 0) { | ||
842 | dev_err(tspi->dev, | ||
843 | "spi can not start transfer, err %d\n", ret); | ||
844 | goto exit; | ||
845 | } | ||
846 | is_first_msg = false; | ||
847 | ret = wait_for_completion_timeout(&tspi->xfer_completion, | ||
848 | SLINK_DMA_TIMEOUT); | ||
849 | if (WARN_ON(ret == 0)) { | ||
850 | dev_err(tspi->dev, | ||
851 | "spi trasfer timeout, err %d\n", ret); | ||
852 | ret = -EIO; | ||
853 | goto exit; | ||
854 | } | ||
855 | 836 | ||
856 | if (tspi->tx_status || tspi->rx_status) { | 837 | static int tegra_slink_transfer_one(struct spi_master *master, |
857 | dev_err(tspi->dev, "Error in Transfer\n"); | 838 | struct spi_device *spi, |
858 | ret = -EIO; | 839 | struct spi_transfer *xfer) |
859 | goto exit; | 840 | { |
860 | } | 841 | struct tegra_slink_data *tspi = spi_master_get_devdata(master); |
861 | msg->actual_length += xfer->len; | 842 | int ret; |
862 | if (xfer->cs_change && xfer->delay_usecs) { | 843 | |
863 | tegra_slink_writel(tspi, tspi->def_command_reg, | 844 | INIT_COMPLETION(tspi->xfer_completion); |
864 | SLINK_COMMAND); | 845 | ret = tegra_slink_start_transfer_one(spi, xfer, tspi->is_first_msg); |
865 | udelay(xfer->delay_usecs); | 846 | if (ret < 0) { |
866 | } | 847 | dev_err(tspi->dev, |
848 | "spi can not start transfer, err %d\n", ret); | ||
849 | return ret; | ||
867 | } | 850 | } |
868 | ret = 0; | 851 | tspi->is_first_msg = false; |
869 | exit: | 852 | ret = wait_for_completion_timeout(&tspi->xfer_completion, |
853 | SLINK_DMA_TIMEOUT); | ||
854 | if (WARN_ON(ret == 0)) { | ||
855 | dev_err(tspi->dev, | ||
856 | "spi trasfer timeout, err %d\n", ret); | ||
857 | return -EIO; | ||
858 | } | ||
859 | |||
860 | if (tspi->tx_status) | ||
861 | return tspi->tx_status; | ||
862 | if (tspi->rx_status) | ||
863 | return tspi->rx_status; | ||
864 | |||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | static int tegra_slink_unprepare_message(struct spi_master *master, | ||
869 | struct spi_message *msg) | ||
870 | { | ||
871 | struct tegra_slink_data *tspi = spi_master_get_devdata(master); | ||
872 | |||
870 | tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); | 873 | tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND); |
871 | tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); | 874 | tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2); |
872 | msg->status = ret; | 875 | |
873 | spi_finalize_current_message(master); | 876 | return 0; |
874 | return ret; | ||
875 | } | 877 | } |
876 | 878 | ||
877 | static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi) | 879 | static irqreturn_t handle_cpu_based_xfer(struct tegra_slink_data *tspi) |
@@ -1074,7 +1076,9 @@ static int tegra_slink_probe(struct platform_device *pdev) | |||
1074 | /* the spi->mode bits understood by this driver: */ | 1076 | /* the spi->mode bits understood by this driver: */ |
1075 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; | 1077 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
1076 | master->setup = tegra_slink_setup; | 1078 | master->setup = tegra_slink_setup; |
1077 | master->transfer_one_message = tegra_slink_transfer_one_message; | 1079 | master->prepare_message = tegra_slink_prepare_message; |
1080 | master->transfer_one = tegra_slink_transfer_one; | ||
1081 | master->unprepare_message = tegra_slink_unprepare_message; | ||
1078 | master->auto_runtime_pm = true; | 1082 | master->auto_runtime_pm = true; |
1079 | master->num_chipselect = MAX_CHIP_SELECT; | 1083 | master->num_chipselect = MAX_CHIP_SELECT; |
1080 | master->bus_num = -1; | 1084 | master->bus_num = -1; |