| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * SPI driver for Nvidia's Tegra20/Tegra30 SLINK Controller. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 7 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 8 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 11 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 12 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 13 | | - * more details. |
|---|
| 14 | | - * |
|---|
| 15 | | - * You should have received a copy of the GNU General Public License |
|---|
| 16 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 17 | 6 | */ |
|---|
| 18 | 7 | |
|---|
| 19 | 8 | #include <linux/clk.h> |
|---|
| .. | .. |
|---|
| 610 | 599 | int ret; |
|---|
| 611 | 600 | struct dma_slave_config dma_sconfig; |
|---|
| 612 | 601 | |
|---|
| 613 | | - dma_chan = dma_request_slave_channel_reason(tspi->dev, |
|---|
| 614 | | - dma_to_memory ? "rx" : "tx"); |
|---|
| 615 | | - if (IS_ERR(dma_chan)) { |
|---|
| 616 | | - ret = PTR_ERR(dma_chan); |
|---|
| 617 | | - if (ret != -EPROBE_DEFER) |
|---|
| 618 | | - dev_err(tspi->dev, |
|---|
| 619 | | - "Dma channel is not available: %d\n", ret); |
|---|
| 620 | | - return ret; |
|---|
| 621 | | - } |
|---|
| 602 | + dma_chan = dma_request_chan(tspi->dev, dma_to_memory ? "rx" : "tx"); |
|---|
| 603 | + if (IS_ERR(dma_chan)) |
|---|
| 604 | + return dev_err_probe(tspi->dev, PTR_ERR(dma_chan), |
|---|
| 605 | + "Dma channel is not available\n"); |
|---|
| 622 | 606 | |
|---|
| 623 | 607 | dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size, |
|---|
| 624 | 608 | &dma_phys, GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 717 | 701 | command2 = tspi->command2_reg; |
|---|
| 718 | 702 | command2 &= ~(SLINK_RXEN | SLINK_TXEN); |
|---|
| 719 | 703 | |
|---|
| 720 | | - tegra_slink_writel(tspi, command, SLINK_COMMAND); |
|---|
| 721 | | - tspi->command_reg = command; |
|---|
| 722 | | - |
|---|
| 723 | 704 | tspi->cur_direction = 0; |
|---|
| 724 | 705 | if (t->rx_buf) { |
|---|
| 725 | 706 | command2 |= SLINK_RXEN; |
|---|
| .. | .. |
|---|
| 729 | 710 | command2 |= SLINK_TXEN; |
|---|
| 730 | 711 | tspi->cur_direction |= DATA_DIR_TX; |
|---|
| 731 | 712 | } |
|---|
| 713 | + |
|---|
| 714 | + /* |
|---|
| 715 | + * Writing to the command2 register bevore the command register prevents |
|---|
| 716 | + * a spike in chip_select line 0. This selects the chip_select line |
|---|
| 717 | + * before changing the chip_select value. |
|---|
| 718 | + */ |
|---|
| 732 | 719 | tegra_slink_writel(tspi, command2, SLINK_COMMAND2); |
|---|
| 733 | 720 | tspi->command2_reg = command2; |
|---|
| 721 | + |
|---|
| 722 | + tegra_slink_writel(tspi, command, SLINK_COMMAND); |
|---|
| 723 | + tspi->command_reg = command; |
|---|
| 734 | 724 | |
|---|
| 735 | 725 | if (total_fifo_words > SLINK_FIFO_DEPTH) |
|---|
| 736 | 726 | ret = tegra_slink_start_dma_based_transfer(tspi, t); |
|---|
| .. | .. |
|---|
| 1016 | 1006 | struct resource *r; |
|---|
| 1017 | 1007 | int ret, spi_irq; |
|---|
| 1018 | 1008 | const struct tegra_slink_chip_data *cdata = NULL; |
|---|
| 1019 | | - const struct of_device_id *match; |
|---|
| 1020 | 1009 | |
|---|
| 1021 | | - match = of_match_device(tegra_slink_of_match, &pdev->dev); |
|---|
| 1022 | | - if (!match) { |
|---|
| 1023 | | - dev_err(&pdev->dev, "Error: No device match found\n"); |
|---|
| 1024 | | - return -ENODEV; |
|---|
| 1025 | | - } |
|---|
| 1026 | | - cdata = match->data; |
|---|
| 1010 | + cdata = of_device_get_match_data(&pdev->dev); |
|---|
| 1027 | 1011 | |
|---|
| 1028 | 1012 | master = spi_alloc_master(&pdev->dev, sizeof(*tspi)); |
|---|
| 1029 | 1013 | if (!master) { |
|---|
| .. | .. |
|---|
| 1125 | 1109 | ret = pm_runtime_get_sync(&pdev->dev); |
|---|
| 1126 | 1110 | if (ret < 0) { |
|---|
| 1127 | 1111 | dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret); |
|---|
| 1112 | + pm_runtime_put_noidle(&pdev->dev); |
|---|
| 1128 | 1113 | goto exit_pm_disable; |
|---|
| 1129 | 1114 | } |
|---|
| 1130 | 1115 | tspi->def_command_reg = SLINK_M_S; |
|---|