| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * SPI driver for NVIDIA's Tegra114 SPI Controller. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (c) 2013, 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> |
|---|
| .. | .. |
|---|
| 95 | 84 | (reg = (((val) & 0x1) << ((cs) * 8 + 5)) | \ |
|---|
| 96 | 85 | ((reg) & ~(1 << ((cs) * 8 + 5)))) |
|---|
| 97 | 86 | #define SPI_SET_CYCLES_BETWEEN_PACKETS(reg, cs, val) \ |
|---|
| 98 | | - (reg = (((val) & 0xF) << ((cs) * 8)) | \ |
|---|
| 99 | | - ((reg) & ~(0xF << ((cs) * 8)))) |
|---|
| 87 | + (reg = (((val) & 0x1F) << ((cs) * 8)) | \ |
|---|
| 88 | + ((reg) & ~(0x1F << ((cs) * 8)))) |
|---|
| 89 | +#define MAX_SETUP_HOLD_CYCLES 16 |
|---|
| 90 | +#define MAX_INACTIVE_CYCLES 32 |
|---|
| 100 | 91 | |
|---|
| 101 | 92 | #define SPI_TRANS_STATUS 0x010 |
|---|
| 102 | 93 | #define SPI_BLK_CNT(val) (((val) >> 0) & 0xFFFF) |
|---|
| .. | .. |
|---|
| 149 | 140 | |
|---|
| 150 | 141 | #define SPI_TX_FIFO 0x108 |
|---|
| 151 | 142 | #define SPI_RX_FIFO 0x188 |
|---|
| 143 | +#define SPI_INTR_MASK 0x18c |
|---|
| 144 | +#define SPI_INTR_ALL_MASK (0x1fUL << 25) |
|---|
| 152 | 145 | #define MAX_CHIP_SELECT 4 |
|---|
| 153 | 146 | #define SPI_FIFO_DEPTH 64 |
|---|
| 154 | 147 | #define DATA_DIR_TX (1 << 0) |
|---|
| .. | .. |
|---|
| 160 | 153 | #define RX_FIFO_FULL_COUNT_ZERO SPI_RX_FIFO_FULL_COUNT(0) |
|---|
| 161 | 154 | #define MAX_HOLD_CYCLES 16 |
|---|
| 162 | 155 | #define SPI_DEFAULT_SPEED 25000000 |
|---|
| 156 | + |
|---|
| 157 | +struct tegra_spi_soc_data { |
|---|
| 158 | + bool has_intr_mask_reg; |
|---|
| 159 | +}; |
|---|
| 160 | + |
|---|
| 161 | +struct tegra_spi_client_data { |
|---|
| 162 | + int tx_clk_tap_delay; |
|---|
| 163 | + int rx_clk_tap_delay; |
|---|
| 164 | +}; |
|---|
| 163 | 165 | |
|---|
| 164 | 166 | struct tegra_spi_data { |
|---|
| 165 | 167 | struct device *dev; |
|---|
| .. | .. |
|---|
| 187 | 189 | unsigned dma_buf_size; |
|---|
| 188 | 190 | unsigned max_buf_size; |
|---|
| 189 | 191 | bool is_curr_dma_xfer; |
|---|
| 192 | + bool use_hw_based_cs; |
|---|
| 190 | 193 | |
|---|
| 191 | 194 | struct completion rx_dma_complete; |
|---|
| 192 | 195 | struct completion tx_dma_complete; |
|---|
| .. | .. |
|---|
| 199 | 202 | u32 command1_reg; |
|---|
| 200 | 203 | u32 dma_control_reg; |
|---|
| 201 | 204 | u32 def_command1_reg; |
|---|
| 205 | + u32 def_command2_reg; |
|---|
| 206 | + u32 spi_cs_timing1; |
|---|
| 207 | + u32 spi_cs_timing2; |
|---|
| 208 | + u8 last_used_cs; |
|---|
| 202 | 209 | |
|---|
| 203 | 210 | struct completion xfer_completion; |
|---|
| 204 | 211 | struct spi_transfer *curr_xfer; |
|---|
| .. | .. |
|---|
| 211 | 218 | u32 *tx_dma_buf; |
|---|
| 212 | 219 | dma_addr_t tx_dma_phys; |
|---|
| 213 | 220 | struct dma_async_tx_descriptor *tx_dma_desc; |
|---|
| 221 | + const struct tegra_spi_soc_data *soc_data; |
|---|
| 214 | 222 | }; |
|---|
| 215 | 223 | |
|---|
| 216 | 224 | static int tegra_spi_runtime_suspend(struct device *dev); |
|---|
| .. | .. |
|---|
| 259 | 267 | |
|---|
| 260 | 268 | tspi->bytes_per_word = DIV_ROUND_UP(bits_per_word, 8); |
|---|
| 261 | 269 | |
|---|
| 262 | | - if (bits_per_word == 8 || bits_per_word == 16) { |
|---|
| 263 | | - tspi->is_packed = 1; |
|---|
| 270 | + if ((bits_per_word == 8 || bits_per_word == 16 || |
|---|
| 271 | + bits_per_word == 32) && t->len > 3) { |
|---|
| 272 | + tspi->is_packed = true; |
|---|
| 264 | 273 | tspi->words_per_32bit = 32/bits_per_word; |
|---|
| 265 | 274 | } else { |
|---|
| 266 | | - tspi->is_packed = 0; |
|---|
| 275 | + tspi->is_packed = false; |
|---|
| 267 | 276 | tspi->words_per_32bit = 1; |
|---|
| 268 | 277 | } |
|---|
| 269 | 278 | |
|---|
| .. | .. |
|---|
| 553 | 562 | dma_burst = 8; |
|---|
| 554 | 563 | } |
|---|
| 555 | 564 | |
|---|
| 556 | | - if (tspi->cur_direction & DATA_DIR_TX) |
|---|
| 557 | | - val |= SPI_IE_TX; |
|---|
| 565 | + if (!tspi->soc_data->has_intr_mask_reg) { |
|---|
| 566 | + if (tspi->cur_direction & DATA_DIR_TX) |
|---|
| 567 | + val |= SPI_IE_TX; |
|---|
| 558 | 568 | |
|---|
| 559 | | - if (tspi->cur_direction & DATA_DIR_RX) |
|---|
| 560 | | - val |= SPI_IE_RX; |
|---|
| 569 | + if (tspi->cur_direction & DATA_DIR_RX) |
|---|
| 570 | + val |= SPI_IE_RX; |
|---|
| 571 | + } |
|---|
| 561 | 572 | |
|---|
| 562 | 573 | tegra_spi_writel(tspi, val, SPI_DMA_CTL); |
|---|
| 563 | 574 | tspi->dma_control_reg = val; |
|---|
| .. | .. |
|---|
| 641 | 652 | |
|---|
| 642 | 653 | tspi->is_curr_dma_xfer = false; |
|---|
| 643 | 654 | |
|---|
| 644 | | - val |= SPI_DMA_EN; |
|---|
| 645 | | - tegra_spi_writel(tspi, val, SPI_DMA_CTL); |
|---|
| 655 | + val = tspi->command1_reg; |
|---|
| 656 | + val |= SPI_PIO; |
|---|
| 657 | + tegra_spi_writel(tspi, val, SPI_COMMAND1); |
|---|
| 646 | 658 | return 0; |
|---|
| 647 | 659 | } |
|---|
| 648 | 660 | |
|---|
| .. | .. |
|---|
| 652 | 664 | struct dma_chan *dma_chan; |
|---|
| 653 | 665 | u32 *dma_buf; |
|---|
| 654 | 666 | dma_addr_t dma_phys; |
|---|
| 655 | | - int ret; |
|---|
| 656 | 667 | |
|---|
| 657 | | - dma_chan = dma_request_slave_channel_reason(tspi->dev, |
|---|
| 658 | | - dma_to_memory ? "rx" : "tx"); |
|---|
| 659 | | - if (IS_ERR(dma_chan)) { |
|---|
| 660 | | - ret = PTR_ERR(dma_chan); |
|---|
| 661 | | - if (ret != -EPROBE_DEFER) |
|---|
| 662 | | - dev_err(tspi->dev, |
|---|
| 663 | | - "Dma channel is not available: %d\n", ret); |
|---|
| 664 | | - return ret; |
|---|
| 665 | | - } |
|---|
| 668 | + dma_chan = dma_request_chan(tspi->dev, dma_to_memory ? "rx" : "tx"); |
|---|
| 669 | + if (IS_ERR(dma_chan)) |
|---|
| 670 | + return dev_err_probe(tspi->dev, PTR_ERR(dma_chan), |
|---|
| 671 | + "Dma channel is not available\n"); |
|---|
| 666 | 672 | |
|---|
| 667 | 673 | dma_buf = dma_alloc_coherent(tspi->dev, tspi->dma_buf_size, |
|---|
| 668 | 674 | &dma_phys, GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 711 | 717 | dma_release_channel(dma_chan); |
|---|
| 712 | 718 | } |
|---|
| 713 | 719 | |
|---|
| 714 | | -static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, |
|---|
| 715 | | - struct spi_transfer *t, bool is_first_of_msg) |
|---|
| 720 | +static int tegra_spi_set_hw_cs_timing(struct spi_device *spi, |
|---|
| 721 | + struct spi_delay *setup, |
|---|
| 722 | + struct spi_delay *hold, |
|---|
| 723 | + struct spi_delay *inactive) |
|---|
| 716 | 724 | { |
|---|
| 717 | 725 | struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); |
|---|
| 726 | + u8 setup_dly, hold_dly, inactive_dly; |
|---|
| 727 | + u32 setup_hold; |
|---|
| 728 | + u32 spi_cs_timing; |
|---|
| 729 | + u32 inactive_cycles; |
|---|
| 730 | + u8 cs_state; |
|---|
| 731 | + |
|---|
| 732 | + if ((setup && setup->unit != SPI_DELAY_UNIT_SCK) || |
|---|
| 733 | + (hold && hold->unit != SPI_DELAY_UNIT_SCK) || |
|---|
| 734 | + (inactive && inactive->unit != SPI_DELAY_UNIT_SCK)) { |
|---|
| 735 | + dev_err(&spi->dev, |
|---|
| 736 | + "Invalid delay unit %d, should be SPI_DELAY_UNIT_SCK\n", |
|---|
| 737 | + SPI_DELAY_UNIT_SCK); |
|---|
| 738 | + return -EINVAL; |
|---|
| 739 | + } |
|---|
| 740 | + |
|---|
| 741 | + setup_dly = setup ? setup->value : 0; |
|---|
| 742 | + hold_dly = hold ? hold->value : 0; |
|---|
| 743 | + inactive_dly = inactive ? inactive->value : 0; |
|---|
| 744 | + |
|---|
| 745 | + setup_dly = min_t(u8, setup_dly, MAX_SETUP_HOLD_CYCLES); |
|---|
| 746 | + hold_dly = min_t(u8, hold_dly, MAX_SETUP_HOLD_CYCLES); |
|---|
| 747 | + if (setup_dly && hold_dly) { |
|---|
| 748 | + setup_hold = SPI_SETUP_HOLD(setup_dly - 1, hold_dly - 1); |
|---|
| 749 | + spi_cs_timing = SPI_CS_SETUP_HOLD(tspi->spi_cs_timing1, |
|---|
| 750 | + spi->chip_select, |
|---|
| 751 | + setup_hold); |
|---|
| 752 | + if (tspi->spi_cs_timing1 != spi_cs_timing) { |
|---|
| 753 | + tspi->spi_cs_timing1 = spi_cs_timing; |
|---|
| 754 | + tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING1); |
|---|
| 755 | + } |
|---|
| 756 | + } |
|---|
| 757 | + |
|---|
| 758 | + inactive_cycles = min_t(u8, inactive_dly, MAX_INACTIVE_CYCLES); |
|---|
| 759 | + if (inactive_cycles) |
|---|
| 760 | + inactive_cycles--; |
|---|
| 761 | + cs_state = inactive_cycles ? 0 : 1; |
|---|
| 762 | + spi_cs_timing = tspi->spi_cs_timing2; |
|---|
| 763 | + SPI_SET_CS_ACTIVE_BETWEEN_PACKETS(spi_cs_timing, spi->chip_select, |
|---|
| 764 | + cs_state); |
|---|
| 765 | + SPI_SET_CYCLES_BETWEEN_PACKETS(spi_cs_timing, spi->chip_select, |
|---|
| 766 | + inactive_cycles); |
|---|
| 767 | + if (tspi->spi_cs_timing2 != spi_cs_timing) { |
|---|
| 768 | + tspi->spi_cs_timing2 = spi_cs_timing; |
|---|
| 769 | + tegra_spi_writel(tspi, spi_cs_timing, SPI_CS_TIMING2); |
|---|
| 770 | + } |
|---|
| 771 | + |
|---|
| 772 | + return 0; |
|---|
| 773 | +} |
|---|
| 774 | + |
|---|
| 775 | +static u32 tegra_spi_setup_transfer_one(struct spi_device *spi, |
|---|
| 776 | + struct spi_transfer *t, |
|---|
| 777 | + bool is_first_of_msg, |
|---|
| 778 | + bool is_single_xfer) |
|---|
| 779 | +{ |
|---|
| 780 | + struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); |
|---|
| 781 | + struct tegra_spi_client_data *cdata = spi->controller_data; |
|---|
| 718 | 782 | u32 speed = t->speed_hz; |
|---|
| 719 | 783 | u8 bits_per_word = t->bits_per_word; |
|---|
| 720 | | - u32 command1; |
|---|
| 784 | + u32 command1, command2; |
|---|
| 721 | 785 | int req_mode; |
|---|
| 786 | + u32 tx_tap = 0, rx_tap = 0; |
|---|
| 722 | 787 | |
|---|
| 723 | 788 | if (speed != tspi->cur_speed) { |
|---|
| 724 | 789 | clk_set_rate(tspi->clk, speed); |
|---|
| .. | .. |
|---|
| 748 | 813 | else if (req_mode == SPI_MODE_3) |
|---|
| 749 | 814 | command1 |= SPI_CONTROL_MODE_3; |
|---|
| 750 | 815 | |
|---|
| 816 | + if (spi->mode & SPI_LSB_FIRST) |
|---|
| 817 | + command1 |= SPI_LSBIT_FE; |
|---|
| 818 | + else |
|---|
| 819 | + command1 &= ~SPI_LSBIT_FE; |
|---|
| 820 | + |
|---|
| 821 | + if (spi->mode & SPI_3WIRE) |
|---|
| 822 | + command1 |= SPI_BIDIROE; |
|---|
| 823 | + else |
|---|
| 824 | + command1 &= ~SPI_BIDIROE; |
|---|
| 825 | + |
|---|
| 751 | 826 | if (tspi->cs_control) { |
|---|
| 752 | 827 | if (tspi->cs_control != spi) |
|---|
| 753 | 828 | tegra_spi_writel(tspi, command1, SPI_COMMAND1); |
|---|
| .. | .. |
|---|
| 755 | 830 | } else |
|---|
| 756 | 831 | tegra_spi_writel(tspi, command1, SPI_COMMAND1); |
|---|
| 757 | 832 | |
|---|
| 758 | | - command1 |= SPI_CS_SW_HW; |
|---|
| 759 | | - if (spi->mode & SPI_CS_HIGH) |
|---|
| 760 | | - command1 |= SPI_CS_SW_VAL; |
|---|
| 761 | | - else |
|---|
| 762 | | - command1 &= ~SPI_CS_SW_VAL; |
|---|
| 833 | + /* GPIO based chip select control */ |
|---|
| 834 | + if (spi->cs_gpiod) |
|---|
| 835 | + gpiod_set_value(spi->cs_gpiod, 1); |
|---|
| 763 | 836 | |
|---|
| 764 | | - tegra_spi_writel(tspi, 0, SPI_COMMAND2); |
|---|
| 837 | + if (is_single_xfer && !(t->cs_change)) { |
|---|
| 838 | + tspi->use_hw_based_cs = true; |
|---|
| 839 | + command1 &= ~(SPI_CS_SW_HW | SPI_CS_SW_VAL); |
|---|
| 840 | + } else { |
|---|
| 841 | + tspi->use_hw_based_cs = false; |
|---|
| 842 | + command1 |= SPI_CS_SW_HW; |
|---|
| 843 | + if (spi->mode & SPI_CS_HIGH) |
|---|
| 844 | + command1 |= SPI_CS_SW_VAL; |
|---|
| 845 | + else |
|---|
| 846 | + command1 &= ~SPI_CS_SW_VAL; |
|---|
| 847 | + } |
|---|
| 848 | + |
|---|
| 849 | + if (tspi->last_used_cs != spi->chip_select) { |
|---|
| 850 | + if (cdata && cdata->tx_clk_tap_delay) |
|---|
| 851 | + tx_tap = cdata->tx_clk_tap_delay; |
|---|
| 852 | + if (cdata && cdata->rx_clk_tap_delay) |
|---|
| 853 | + rx_tap = cdata->rx_clk_tap_delay; |
|---|
| 854 | + command2 = SPI_TX_TAP_DELAY(tx_tap) | |
|---|
| 855 | + SPI_RX_TAP_DELAY(rx_tap); |
|---|
| 856 | + if (command2 != tspi->def_command2_reg) |
|---|
| 857 | + tegra_spi_writel(tspi, command2, SPI_COMMAND2); |
|---|
| 858 | + tspi->last_used_cs = spi->chip_select; |
|---|
| 859 | + } |
|---|
| 860 | + |
|---|
| 765 | 861 | } else { |
|---|
| 766 | 862 | command1 = tspi->command1_reg; |
|---|
| 767 | 863 | command1 &= ~SPI_BIT_LENGTH(~0); |
|---|
| .. | .. |
|---|
| 779 | 875 | int ret; |
|---|
| 780 | 876 | |
|---|
| 781 | 877 | total_fifo_words = tegra_spi_calculate_curr_xfer_param(spi, tspi, t); |
|---|
| 878 | + |
|---|
| 879 | + if (t->rx_nbits == SPI_NBITS_DUAL || t->tx_nbits == SPI_NBITS_DUAL) |
|---|
| 880 | + command1 |= SPI_BOTH_EN_BIT; |
|---|
| 881 | + else |
|---|
| 882 | + command1 &= ~SPI_BOTH_EN_BIT; |
|---|
| 782 | 883 | |
|---|
| 783 | 884 | if (tspi->is_packed) |
|---|
| 784 | 885 | command1 |= SPI_PACKED; |
|---|
| .. | .. |
|---|
| 812 | 913 | return ret; |
|---|
| 813 | 914 | } |
|---|
| 814 | 915 | |
|---|
| 916 | +static struct tegra_spi_client_data |
|---|
| 917 | + *tegra_spi_parse_cdata_dt(struct spi_device *spi) |
|---|
| 918 | +{ |
|---|
| 919 | + struct tegra_spi_client_data *cdata; |
|---|
| 920 | + struct device_node *slave_np; |
|---|
| 921 | + |
|---|
| 922 | + slave_np = spi->dev.of_node; |
|---|
| 923 | + if (!slave_np) { |
|---|
| 924 | + dev_dbg(&spi->dev, "device node not found\n"); |
|---|
| 925 | + return NULL; |
|---|
| 926 | + } |
|---|
| 927 | + |
|---|
| 928 | + cdata = kzalloc(sizeof(*cdata), GFP_KERNEL); |
|---|
| 929 | + if (!cdata) |
|---|
| 930 | + return NULL; |
|---|
| 931 | + |
|---|
| 932 | + of_property_read_u32(slave_np, "nvidia,tx-clk-tap-delay", |
|---|
| 933 | + &cdata->tx_clk_tap_delay); |
|---|
| 934 | + of_property_read_u32(slave_np, "nvidia,rx-clk-tap-delay", |
|---|
| 935 | + &cdata->rx_clk_tap_delay); |
|---|
| 936 | + return cdata; |
|---|
| 937 | +} |
|---|
| 938 | + |
|---|
| 939 | +static void tegra_spi_cleanup(struct spi_device *spi) |
|---|
| 940 | +{ |
|---|
| 941 | + struct tegra_spi_client_data *cdata = spi->controller_data; |
|---|
| 942 | + |
|---|
| 943 | + spi->controller_data = NULL; |
|---|
| 944 | + if (spi->dev.of_node) |
|---|
| 945 | + kfree(cdata); |
|---|
| 946 | +} |
|---|
| 947 | + |
|---|
| 815 | 948 | static int tegra_spi_setup(struct spi_device *spi) |
|---|
| 816 | 949 | { |
|---|
| 817 | 950 | struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); |
|---|
| 951 | + struct tegra_spi_client_data *cdata = spi->controller_data; |
|---|
| 818 | 952 | u32 val; |
|---|
| 819 | 953 | unsigned long flags; |
|---|
| 820 | 954 | int ret; |
|---|
| .. | .. |
|---|
| 825 | 959 | spi->mode & SPI_CPHA ? "" : "~", |
|---|
| 826 | 960 | spi->max_speed_hz); |
|---|
| 827 | 961 | |
|---|
| 962 | + if (!cdata) { |
|---|
| 963 | + cdata = tegra_spi_parse_cdata_dt(spi); |
|---|
| 964 | + spi->controller_data = cdata; |
|---|
| 965 | + } |
|---|
| 966 | + |
|---|
| 828 | 967 | ret = pm_runtime_get_sync(tspi->dev); |
|---|
| 829 | 968 | if (ret < 0) { |
|---|
| 830 | 969 | pm_runtime_put_noidle(tspi->dev); |
|---|
| 831 | 970 | dev_err(tspi->dev, "pm runtime failed, e = %d\n", ret); |
|---|
| 971 | + if (cdata) |
|---|
| 972 | + tegra_spi_cleanup(spi); |
|---|
| 832 | 973 | return ret; |
|---|
| 833 | 974 | } |
|---|
| 834 | 975 | |
|---|
| 976 | + if (tspi->soc_data->has_intr_mask_reg) { |
|---|
| 977 | + val = tegra_spi_readl(tspi, SPI_INTR_MASK); |
|---|
| 978 | + val &= ~SPI_INTR_ALL_MASK; |
|---|
| 979 | + tegra_spi_writel(tspi, val, SPI_INTR_MASK); |
|---|
| 980 | + } |
|---|
| 981 | + |
|---|
| 835 | 982 | spin_lock_irqsave(&tspi->lock, flags); |
|---|
| 983 | + /* GPIO based chip select control */ |
|---|
| 984 | + if (spi->cs_gpiod) |
|---|
| 985 | + gpiod_set_value(spi->cs_gpiod, 0); |
|---|
| 986 | + |
|---|
| 836 | 987 | val = tspi->def_command1_reg; |
|---|
| 837 | 988 | if (spi->mode & SPI_CS_HIGH) |
|---|
| 838 | 989 | val &= ~SPI_CS_POL_INACTIVE(spi->chip_select); |
|---|
| .. | .. |
|---|
| 846 | 997 | return 0; |
|---|
| 847 | 998 | } |
|---|
| 848 | 999 | |
|---|
| 849 | | -static void tegra_spi_transfer_delay(int delay) |
|---|
| 1000 | +static void tegra_spi_transfer_end(struct spi_device *spi) |
|---|
| 850 | 1001 | { |
|---|
| 851 | | - if (!delay) |
|---|
| 852 | | - return; |
|---|
| 1002 | + struct tegra_spi_data *tspi = spi_master_get_devdata(spi->master); |
|---|
| 1003 | + int cs_val = (spi->mode & SPI_CS_HIGH) ? 0 : 1; |
|---|
| 853 | 1004 | |
|---|
| 854 | | - if (delay >= 1000) |
|---|
| 855 | | - mdelay(delay / 1000); |
|---|
| 1005 | + /* GPIO based chip select control */ |
|---|
| 1006 | + if (spi->cs_gpiod) |
|---|
| 1007 | + gpiod_set_value(spi->cs_gpiod, 0); |
|---|
| 856 | 1008 | |
|---|
| 857 | | - udelay(delay % 1000); |
|---|
| 1009 | + if (!tspi->use_hw_based_cs) { |
|---|
| 1010 | + if (cs_val) |
|---|
| 1011 | + tspi->command1_reg |= SPI_CS_SW_VAL; |
|---|
| 1012 | + else |
|---|
| 1013 | + tspi->command1_reg &= ~SPI_CS_SW_VAL; |
|---|
| 1014 | + tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1); |
|---|
| 1015 | + } |
|---|
| 1016 | + |
|---|
| 1017 | + tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); |
|---|
| 1018 | +} |
|---|
| 1019 | + |
|---|
| 1020 | +static void tegra_spi_dump_regs(struct tegra_spi_data *tspi) |
|---|
| 1021 | +{ |
|---|
| 1022 | + dev_dbg(tspi->dev, "============ SPI REGISTER DUMP ============\n"); |
|---|
| 1023 | + dev_dbg(tspi->dev, "Command1: 0x%08x | Command2: 0x%08x\n", |
|---|
| 1024 | + tegra_spi_readl(tspi, SPI_COMMAND1), |
|---|
| 1025 | + tegra_spi_readl(tspi, SPI_COMMAND2)); |
|---|
| 1026 | + dev_dbg(tspi->dev, "DMA_CTL: 0x%08x | DMA_BLK: 0x%08x\n", |
|---|
| 1027 | + tegra_spi_readl(tspi, SPI_DMA_CTL), |
|---|
| 1028 | + tegra_spi_readl(tspi, SPI_DMA_BLK)); |
|---|
| 1029 | + dev_dbg(tspi->dev, "TRANS_STAT: 0x%08x | FIFO_STATUS: 0x%08x\n", |
|---|
| 1030 | + tegra_spi_readl(tspi, SPI_TRANS_STATUS), |
|---|
| 1031 | + tegra_spi_readl(tspi, SPI_FIFO_STATUS)); |
|---|
| 858 | 1032 | } |
|---|
| 859 | 1033 | |
|---|
| 860 | 1034 | static int tegra_spi_transfer_one_message(struct spi_master *master, |
|---|
| .. | .. |
|---|
| 866 | 1040 | struct spi_device *spi = msg->spi; |
|---|
| 867 | 1041 | int ret; |
|---|
| 868 | 1042 | bool skip = false; |
|---|
| 1043 | + int single_xfer; |
|---|
| 869 | 1044 | |
|---|
| 870 | 1045 | msg->status = 0; |
|---|
| 871 | 1046 | msg->actual_length = 0; |
|---|
| 872 | 1047 | |
|---|
| 1048 | + single_xfer = list_is_singular(&msg->transfers); |
|---|
| 873 | 1049 | list_for_each_entry(xfer, &msg->transfers, transfer_list) { |
|---|
| 874 | 1050 | u32 cmd1; |
|---|
| 875 | 1051 | |
|---|
| 876 | 1052 | reinit_completion(&tspi->xfer_completion); |
|---|
| 877 | 1053 | |
|---|
| 878 | | - cmd1 = tegra_spi_setup_transfer_one(spi, xfer, is_first_msg); |
|---|
| 1054 | + cmd1 = tegra_spi_setup_transfer_one(spi, xfer, is_first_msg, |
|---|
| 1055 | + single_xfer); |
|---|
| 879 | 1056 | |
|---|
| 880 | 1057 | if (!xfer->len) { |
|---|
| 881 | 1058 | ret = 0; |
|---|
| .. | .. |
|---|
| 903 | 1080 | (tspi->cur_direction & DATA_DIR_RX)) |
|---|
| 904 | 1081 | dmaengine_terminate_all(tspi->rx_dma_chan); |
|---|
| 905 | 1082 | ret = -EIO; |
|---|
| 1083 | + tegra_spi_dump_regs(tspi); |
|---|
| 906 | 1084 | tegra_spi_flush_fifos(tspi); |
|---|
| 907 | 1085 | reset_control_assert(tspi->rst); |
|---|
| 908 | 1086 | udelay(2); |
|---|
| 909 | 1087 | reset_control_deassert(tspi->rst); |
|---|
| 1088 | + tspi->last_used_cs = master->num_chipselect + 1; |
|---|
| 910 | 1089 | goto complete_xfer; |
|---|
| 911 | 1090 | } |
|---|
| 912 | 1091 | |
|---|
| 913 | 1092 | if (tspi->tx_status || tspi->rx_status) { |
|---|
| 914 | 1093 | dev_err(tspi->dev, "Error in Transfer\n"); |
|---|
| 915 | 1094 | ret = -EIO; |
|---|
| 1095 | + tegra_spi_dump_regs(tspi); |
|---|
| 916 | 1096 | goto complete_xfer; |
|---|
| 917 | 1097 | } |
|---|
| 918 | 1098 | msg->actual_length += xfer->len; |
|---|
| 919 | 1099 | |
|---|
| 920 | 1100 | complete_xfer: |
|---|
| 921 | 1101 | if (ret < 0 || skip) { |
|---|
| 922 | | - tegra_spi_writel(tspi, tspi->def_command1_reg, |
|---|
| 923 | | - SPI_COMMAND1); |
|---|
| 924 | | - tegra_spi_transfer_delay(xfer->delay_usecs); |
|---|
| 1102 | + tegra_spi_transfer_end(spi); |
|---|
| 1103 | + spi_transfer_delay_exec(xfer); |
|---|
| 925 | 1104 | goto exit; |
|---|
| 926 | 1105 | } else if (list_is_last(&xfer->transfer_list, |
|---|
| 927 | 1106 | &msg->transfers)) { |
|---|
| 928 | 1107 | if (xfer->cs_change) |
|---|
| 929 | 1108 | tspi->cs_control = spi; |
|---|
| 930 | 1109 | else { |
|---|
| 931 | | - tegra_spi_writel(tspi, tspi->def_command1_reg, |
|---|
| 932 | | - SPI_COMMAND1); |
|---|
| 933 | | - tegra_spi_transfer_delay(xfer->delay_usecs); |
|---|
| 1110 | + tegra_spi_transfer_end(spi); |
|---|
| 1111 | + spi_transfer_delay_exec(xfer); |
|---|
| 934 | 1112 | } |
|---|
| 935 | 1113 | } else if (xfer->cs_change) { |
|---|
| 936 | | - tegra_spi_writel(tspi, tspi->def_command1_reg, |
|---|
| 937 | | - SPI_COMMAND1); |
|---|
| 938 | | - tegra_spi_transfer_delay(xfer->delay_usecs); |
|---|
| 1114 | + tegra_spi_transfer_end(spi); |
|---|
| 1115 | + spi_transfer_delay_exec(xfer); |
|---|
| 939 | 1116 | } |
|---|
| 940 | 1117 | |
|---|
| 941 | 1118 | } |
|---|
| .. | .. |
|---|
| 957 | 1134 | tspi->status_reg); |
|---|
| 958 | 1135 | dev_err(tspi->dev, "CpuXfer 0x%08x:0x%08x\n", |
|---|
| 959 | 1136 | tspi->command1_reg, tspi->dma_control_reg); |
|---|
| 1137 | + tegra_spi_dump_regs(tspi); |
|---|
| 960 | 1138 | tegra_spi_flush_fifos(tspi); |
|---|
| 1139 | + complete(&tspi->xfer_completion); |
|---|
| 1140 | + spin_unlock_irqrestore(&tspi->lock, flags); |
|---|
| 961 | 1141 | reset_control_assert(tspi->rst); |
|---|
| 962 | 1142 | udelay(2); |
|---|
| 963 | 1143 | reset_control_deassert(tspi->rst); |
|---|
| 964 | | - complete(&tspi->xfer_completion); |
|---|
| 965 | | - goto exit; |
|---|
| 1144 | + return IRQ_HANDLED; |
|---|
| 966 | 1145 | } |
|---|
| 967 | 1146 | |
|---|
| 968 | 1147 | if (tspi->cur_direction & DATA_DIR_RX) |
|---|
| .. | .. |
|---|
| 1030 | 1209 | tspi->status_reg); |
|---|
| 1031 | 1210 | dev_err(tspi->dev, "DmaXfer 0x%08x:0x%08x\n", |
|---|
| 1032 | 1211 | tspi->command1_reg, tspi->dma_control_reg); |
|---|
| 1212 | + tegra_spi_dump_regs(tspi); |
|---|
| 1033 | 1213 | tegra_spi_flush_fifos(tspi); |
|---|
| 1214 | + complete(&tspi->xfer_completion); |
|---|
| 1215 | + spin_unlock_irqrestore(&tspi->lock, flags); |
|---|
| 1034 | 1216 | reset_control_assert(tspi->rst); |
|---|
| 1035 | 1217 | udelay(2); |
|---|
| 1036 | 1218 | reset_control_deassert(tspi->rst); |
|---|
| 1037 | | - complete(&tspi->xfer_completion); |
|---|
| 1038 | | - spin_unlock_irqrestore(&tspi->lock, flags); |
|---|
| 1039 | 1219 | return IRQ_HANDLED; |
|---|
| 1040 | 1220 | } |
|---|
| 1041 | 1221 | |
|---|
| .. | .. |
|---|
| 1091 | 1271 | return IRQ_WAKE_THREAD; |
|---|
| 1092 | 1272 | } |
|---|
| 1093 | 1273 | |
|---|
| 1274 | +static struct tegra_spi_soc_data tegra114_spi_soc_data = { |
|---|
| 1275 | + .has_intr_mask_reg = false, |
|---|
| 1276 | +}; |
|---|
| 1277 | + |
|---|
| 1278 | +static struct tegra_spi_soc_data tegra124_spi_soc_data = { |
|---|
| 1279 | + .has_intr_mask_reg = false, |
|---|
| 1280 | +}; |
|---|
| 1281 | + |
|---|
| 1282 | +static struct tegra_spi_soc_data tegra210_spi_soc_data = { |
|---|
| 1283 | + .has_intr_mask_reg = true, |
|---|
| 1284 | +}; |
|---|
| 1285 | + |
|---|
| 1094 | 1286 | static const struct of_device_id tegra_spi_of_match[] = { |
|---|
| 1095 | | - { .compatible = "nvidia,tegra114-spi", }, |
|---|
| 1287 | + { |
|---|
| 1288 | + .compatible = "nvidia,tegra114-spi", |
|---|
| 1289 | + .data = &tegra114_spi_soc_data, |
|---|
| 1290 | + }, { |
|---|
| 1291 | + .compatible = "nvidia,tegra124-spi", |
|---|
| 1292 | + .data = &tegra124_spi_soc_data, |
|---|
| 1293 | + }, { |
|---|
| 1294 | + .compatible = "nvidia,tegra210-spi", |
|---|
| 1295 | + .data = &tegra210_spi_soc_data, |
|---|
| 1296 | + }, |
|---|
| 1096 | 1297 | {} |
|---|
| 1097 | 1298 | }; |
|---|
| 1098 | 1299 | MODULE_DEVICE_TABLE(of, tegra_spi_of_match); |
|---|
| .. | .. |
|---|
| 1103 | 1304 | struct tegra_spi_data *tspi; |
|---|
| 1104 | 1305 | struct resource *r; |
|---|
| 1105 | 1306 | int ret, spi_irq; |
|---|
| 1307 | + int bus_num; |
|---|
| 1106 | 1308 | |
|---|
| 1107 | 1309 | master = spi_alloc_master(&pdev->dev, sizeof(*tspi)); |
|---|
| 1108 | 1310 | if (!master) { |
|---|
| .. | .. |
|---|
| 1117 | 1319 | master->max_speed_hz = 25000000; /* 25MHz */ |
|---|
| 1118 | 1320 | |
|---|
| 1119 | 1321 | /* the spi->mode bits understood by this driver: */ |
|---|
| 1120 | | - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; |
|---|
| 1322 | + master->use_gpio_descriptors = true; |
|---|
| 1323 | + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST | |
|---|
| 1324 | + SPI_TX_DUAL | SPI_RX_DUAL | SPI_3WIRE; |
|---|
| 1325 | + master->bits_per_word_mask = SPI_BPW_RANGE_MASK(4, 32); |
|---|
| 1121 | 1326 | master->setup = tegra_spi_setup; |
|---|
| 1327 | + master->cleanup = tegra_spi_cleanup; |
|---|
| 1122 | 1328 | master->transfer_one_message = tegra_spi_transfer_one_message; |
|---|
| 1329 | + master->set_cs_timing = tegra_spi_set_hw_cs_timing; |
|---|
| 1123 | 1330 | master->num_chipselect = MAX_CHIP_SELECT; |
|---|
| 1124 | 1331 | master->auto_runtime_pm = true; |
|---|
| 1332 | + bus_num = of_alias_get_id(pdev->dev.of_node, "spi"); |
|---|
| 1333 | + if (bus_num >= 0) |
|---|
| 1334 | + master->bus_num = bus_num; |
|---|
| 1125 | 1335 | |
|---|
| 1126 | 1336 | tspi->master = master; |
|---|
| 1127 | 1337 | tspi->dev = &pdev->dev; |
|---|
| 1128 | 1338 | spin_lock_init(&tspi->lock); |
|---|
| 1339 | + |
|---|
| 1340 | + tspi->soc_data = of_device_get_match_data(&pdev->dev); |
|---|
| 1341 | + if (!tspi->soc_data) { |
|---|
| 1342 | + dev_err(&pdev->dev, "unsupported tegra\n"); |
|---|
| 1343 | + ret = -ENODEV; |
|---|
| 1344 | + goto exit_free_master; |
|---|
| 1345 | + } |
|---|
| 1129 | 1346 | |
|---|
| 1130 | 1347 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 1131 | 1348 | tspi->base = devm_ioremap_resource(&pdev->dev, r); |
|---|
| .. | .. |
|---|
| 1136 | 1353 | tspi->phys = r->start; |
|---|
| 1137 | 1354 | |
|---|
| 1138 | 1355 | spi_irq = platform_get_irq(pdev, 0); |
|---|
| 1356 | + if (spi_irq < 0) { |
|---|
| 1357 | + ret = spi_irq; |
|---|
| 1358 | + goto exit_free_master; |
|---|
| 1359 | + } |
|---|
| 1139 | 1360 | tspi->irq = spi_irq; |
|---|
| 1140 | 1361 | |
|---|
| 1141 | 1362 | tspi->clk = devm_clk_get(&pdev->dev, "spi"); |
|---|
| .. | .. |
|---|
| 1177 | 1398 | ret = pm_runtime_get_sync(&pdev->dev); |
|---|
| 1178 | 1399 | if (ret < 0) { |
|---|
| 1179 | 1400 | dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret); |
|---|
| 1401 | + pm_runtime_put_noidle(&pdev->dev); |
|---|
| 1180 | 1402 | goto exit_pm_disable; |
|---|
| 1181 | 1403 | } |
|---|
| 1182 | 1404 | |
|---|
| .. | .. |
|---|
| 1185 | 1407 | reset_control_deassert(tspi->rst); |
|---|
| 1186 | 1408 | tspi->def_command1_reg = SPI_M_S; |
|---|
| 1187 | 1409 | tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); |
|---|
| 1410 | + tspi->spi_cs_timing1 = tegra_spi_readl(tspi, SPI_CS_TIMING1); |
|---|
| 1411 | + tspi->spi_cs_timing2 = tegra_spi_readl(tspi, SPI_CS_TIMING2); |
|---|
| 1412 | + tspi->def_command2_reg = tegra_spi_readl(tspi, SPI_COMMAND2); |
|---|
| 1413 | + tspi->last_used_cs = master->num_chipselect + 1; |
|---|
| 1188 | 1414 | pm_runtime_put(&pdev->dev); |
|---|
| 1189 | 1415 | ret = request_threaded_irq(tspi->irq, tegra_spi_isr, |
|---|
| 1190 | 1416 | tegra_spi_isr_thread, IRQF_ONESHOT, |
|---|
| .. | .. |
|---|
| 1258 | 1484 | return ret; |
|---|
| 1259 | 1485 | } |
|---|
| 1260 | 1486 | tegra_spi_writel(tspi, tspi->command1_reg, SPI_COMMAND1); |
|---|
| 1487 | + tegra_spi_writel(tspi, tspi->def_command2_reg, SPI_COMMAND2); |
|---|
| 1488 | + tspi->last_used_cs = master->num_chipselect + 1; |
|---|
| 1261 | 1489 | pm_runtime_put(dev); |
|---|
| 1262 | 1490 | |
|---|
| 1263 | 1491 | return spi_master_resume(master); |
|---|