diff options
Diffstat (limited to 'drivers')
| -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; |
