.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (c) 2008-2014, The Linux foundation. All rights reserved. |
---|
3 | | - * |
---|
4 | | - * This program is free software; you can redistribute it and/or modify |
---|
5 | | - * it under the terms of the GNU General Public License rev 2 and |
---|
6 | | - * only rev 2 as published by the free Software foundation. |
---|
7 | | - * |
---|
8 | | - * This program is distributed in the hope that it will be useful, |
---|
9 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - * MERCHANTABILITY or fITNESS fOR A PARTICULAR PURPOSE. See the |
---|
11 | | - * GNU General Public License for more details. |
---|
12 | 4 | */ |
---|
13 | 5 | |
---|
14 | 6 | #include <linux/clk.h> |
---|
.. | .. |
---|
281 | 273 | writel_relaxed(QUP_OP_IN_SERVICE_FLAG, |
---|
282 | 274 | controller->base + QUP_OPERATIONAL); |
---|
283 | 275 | |
---|
| 276 | + if (!remainder) |
---|
| 277 | + goto exit; |
---|
| 278 | + |
---|
284 | 279 | if (is_block_mode) { |
---|
285 | 280 | num_words = (remainder > words_per_block) ? |
---|
286 | 281 | words_per_block : remainder; |
---|
.. | .. |
---|
310 | 305 | * to refresh opflags value because MAX_INPUT_DONE_FLAG may now be |
---|
311 | 306 | * present and this is used to determine if transaction is complete |
---|
312 | 307 | */ |
---|
313 | | - *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL); |
---|
314 | | - if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG) |
---|
315 | | - writel_relaxed(QUP_OP_IN_SERVICE_FLAG, |
---|
316 | | - controller->base + QUP_OPERATIONAL); |
---|
317 | | - |
---|
| 308 | +exit: |
---|
| 309 | + if (!remainder) { |
---|
| 310 | + *opflags = readl_relaxed(controller->base + QUP_OPERATIONAL); |
---|
| 311 | + if (is_block_mode && *opflags & QUP_OP_MAX_INPUT_DONE_FLAG) |
---|
| 312 | + writel_relaxed(QUP_OP_IN_SERVICE_FLAG, |
---|
| 313 | + controller->base + QUP_OPERATIONAL); |
---|
| 314 | + } |
---|
318 | 315 | } |
---|
319 | 316 | |
---|
320 | 317 | static void spi_qup_write_to_fifo(struct spi_qup *controller, u32 num_words) |
---|
.. | .. |
---|
361 | 358 | /* ACK by clearing service flag */ |
---|
362 | 359 | writel_relaxed(QUP_OP_OUT_SERVICE_FLAG, |
---|
363 | 360 | controller->base + QUP_OPERATIONAL); |
---|
| 361 | + |
---|
| 362 | + /* make sure the interrupt is valid */ |
---|
| 363 | + if (!remainder) |
---|
| 364 | + return; |
---|
364 | 365 | |
---|
365 | 366 | if (is_block_mode) { |
---|
366 | 367 | num_words = (remainder > words_per_block) ? |
---|
.. | .. |
---|
575 | 576 | return 0; |
---|
576 | 577 | } |
---|
577 | 578 | |
---|
| 579 | +static bool spi_qup_data_pending(struct spi_qup *controller) |
---|
| 580 | +{ |
---|
| 581 | + unsigned int remainder_tx, remainder_rx; |
---|
| 582 | + |
---|
| 583 | + remainder_tx = DIV_ROUND_UP(spi_qup_len(controller) - |
---|
| 584 | + controller->tx_bytes, controller->w_size); |
---|
| 585 | + |
---|
| 586 | + remainder_rx = DIV_ROUND_UP(spi_qup_len(controller) - |
---|
| 587 | + controller->rx_bytes, controller->w_size); |
---|
| 588 | + |
---|
| 589 | + return remainder_tx || remainder_rx; |
---|
| 590 | +} |
---|
| 591 | + |
---|
578 | 592 | static irqreturn_t spi_qup_qup_irq(int irq, void *dev_id) |
---|
579 | 593 | { |
---|
580 | 594 | struct spi_qup *controller = dev_id; |
---|
581 | 595 | u32 opflags, qup_err, spi_err; |
---|
| 596 | + unsigned long flags; |
---|
582 | 597 | int error = 0; |
---|
583 | 598 | |
---|
584 | 599 | qup_err = readl_relaxed(controller->base + QUP_ERROR_FLAGS); |
---|
.. | .. |
---|
610 | 625 | error = -EIO; |
---|
611 | 626 | } |
---|
612 | 627 | |
---|
| 628 | + spin_lock_irqsave(&controller->lock, flags); |
---|
| 629 | + if (!controller->error) |
---|
| 630 | + controller->error = error; |
---|
| 631 | + spin_unlock_irqrestore(&controller->lock, flags); |
---|
| 632 | + |
---|
613 | 633 | if (spi_qup_is_dma_xfer(controller->mode)) { |
---|
614 | 634 | writel_relaxed(opflags, controller->base + QUP_OPERATIONAL); |
---|
615 | 635 | } else { |
---|
.. | .. |
---|
618 | 638 | |
---|
619 | 639 | if (opflags & QUP_OP_OUT_SERVICE_FLAG) |
---|
620 | 640 | spi_qup_write(controller); |
---|
| 641 | + |
---|
| 642 | + if (!spi_qup_data_pending(controller)) |
---|
| 643 | + complete(&controller->done); |
---|
621 | 644 | } |
---|
622 | 645 | |
---|
623 | | - if ((opflags & QUP_OP_MAX_INPUT_DONE_FLAG) || error) |
---|
| 646 | + if (error) |
---|
624 | 647 | complete(&controller->done); |
---|
| 648 | + |
---|
| 649 | + if (opflags & QUP_OP_MAX_INPUT_DONE_FLAG) { |
---|
| 650 | + if (!spi_qup_is_dma_xfer(controller->mode)) { |
---|
| 651 | + if (spi_qup_data_pending(controller)) |
---|
| 652 | + return IRQ_HANDLED; |
---|
| 653 | + } |
---|
| 654 | + complete(&controller->done); |
---|
| 655 | + } |
---|
625 | 656 | |
---|
626 | 657 | return IRQ_HANDLED; |
---|
627 | 658 | } |
---|
.. | .. |
---|
817 | 848 | { |
---|
818 | 849 | struct spi_qup *controller = spi_master_get_devdata(master); |
---|
819 | 850 | unsigned long timeout, flags; |
---|
820 | | - int ret = -EIO; |
---|
| 851 | + int ret; |
---|
821 | 852 | |
---|
822 | 853 | ret = spi_qup_io_prep(spi, xfer); |
---|
823 | 854 | if (ret) |
---|
.. | .. |
---|
842 | 873 | else |
---|
843 | 874 | ret = spi_qup_do_pio(spi, xfer, timeout); |
---|
844 | 875 | |
---|
845 | | - if (ret) |
---|
846 | | - goto exit; |
---|
847 | | - |
---|
848 | | -exit: |
---|
849 | 876 | spi_qup_set_state(controller, QUP_STATE_RESET); |
---|
850 | 877 | spin_lock_irqsave(&controller->lock, flags); |
---|
851 | 878 | if (!ret) |
---|
.. | .. |
---|
905 | 932 | int ret; |
---|
906 | 933 | |
---|
907 | 934 | /* allocate dma resources, if available */ |
---|
908 | | - master->dma_rx = dma_request_slave_channel_reason(dev, "rx"); |
---|
| 935 | + master->dma_rx = dma_request_chan(dev, "rx"); |
---|
909 | 936 | if (IS_ERR(master->dma_rx)) |
---|
910 | 937 | return PTR_ERR(master->dma_rx); |
---|
911 | 938 | |
---|
912 | | - master->dma_tx = dma_request_slave_channel_reason(dev, "tx"); |
---|
| 939 | + master->dma_tx = dma_request_chan(dev, "tx"); |
---|
913 | 940 | if (IS_ERR(master->dma_tx)) { |
---|
914 | 941 | ret = PTR_ERR(master->dma_tx); |
---|
915 | 942 | goto err_tx; |
---|
.. | .. |
---|
1003 | 1030 | return -ENXIO; |
---|
1004 | 1031 | } |
---|
1005 | 1032 | |
---|
1006 | | - ret = clk_prepare_enable(cclk); |
---|
1007 | | - if (ret) { |
---|
1008 | | - dev_err(dev, "cannot enable core clock\n"); |
---|
1009 | | - return ret; |
---|
1010 | | - } |
---|
1011 | | - |
---|
1012 | | - ret = clk_prepare_enable(iclk); |
---|
1013 | | - if (ret) { |
---|
1014 | | - clk_disable_unprepare(cclk); |
---|
1015 | | - dev_err(dev, "cannot enable iface clock\n"); |
---|
1016 | | - return ret; |
---|
1017 | | - } |
---|
1018 | | - |
---|
1019 | 1033 | master = spi_alloc_master(dev, sizeof(struct spi_qup)); |
---|
1020 | 1034 | if (!master) { |
---|
1021 | | - clk_disable_unprepare(cclk); |
---|
1022 | | - clk_disable_unprepare(iclk); |
---|
1023 | 1035 | dev_err(dev, "cannot allocate master\n"); |
---|
1024 | 1036 | return -ENOMEM; |
---|
1025 | 1037 | } |
---|
.. | .. |
---|
1065 | 1077 | spin_lock_init(&controller->lock); |
---|
1066 | 1078 | init_completion(&controller->done); |
---|
1067 | 1079 | |
---|
| 1080 | + ret = clk_prepare_enable(cclk); |
---|
| 1081 | + if (ret) { |
---|
| 1082 | + dev_err(dev, "cannot enable core clock\n"); |
---|
| 1083 | + goto error_dma; |
---|
| 1084 | + } |
---|
| 1085 | + |
---|
| 1086 | + ret = clk_prepare_enable(iclk); |
---|
| 1087 | + if (ret) { |
---|
| 1088 | + clk_disable_unprepare(cclk); |
---|
| 1089 | + dev_err(dev, "cannot enable iface clock\n"); |
---|
| 1090 | + goto error_dma; |
---|
| 1091 | + } |
---|
| 1092 | + |
---|
1068 | 1093 | iomode = readl_relaxed(base + QUP_IO_M_MODES); |
---|
1069 | 1094 | |
---|
1070 | 1095 | size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode); |
---|
.. | .. |
---|
1094 | 1119 | ret = spi_qup_set_state(controller, QUP_STATE_RESET); |
---|
1095 | 1120 | if (ret) { |
---|
1096 | 1121 | dev_err(dev, "cannot set RESET state\n"); |
---|
1097 | | - goto error_dma; |
---|
| 1122 | + goto error_clk; |
---|
1098 | 1123 | } |
---|
1099 | 1124 | |
---|
1100 | 1125 | writel_relaxed(0, base + QUP_OPERATIONAL); |
---|
.. | .. |
---|
1118 | 1143 | ret = devm_request_irq(dev, irq, spi_qup_qup_irq, |
---|
1119 | 1144 | IRQF_TRIGGER_HIGH, pdev->name, controller); |
---|
1120 | 1145 | if (ret) |
---|
1121 | | - goto error_dma; |
---|
| 1146 | + goto error_clk; |
---|
1122 | 1147 | |
---|
1123 | 1148 | pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); |
---|
1124 | 1149 | pm_runtime_use_autosuspend(dev); |
---|
.. | .. |
---|
1133 | 1158 | |
---|
1134 | 1159 | disable_pm: |
---|
1135 | 1160 | pm_runtime_disable(&pdev->dev); |
---|
| 1161 | +error_clk: |
---|
| 1162 | + clk_disable_unprepare(cclk); |
---|
| 1163 | + clk_disable_unprepare(iclk); |
---|
1136 | 1164 | error_dma: |
---|
1137 | 1165 | spi_qup_release_dma(master); |
---|
1138 | 1166 | error: |
---|
1139 | | - clk_disable_unprepare(cclk); |
---|
1140 | | - clk_disable_unprepare(iclk); |
---|
1141 | 1167 | spi_master_put(master); |
---|
1142 | 1168 | return ret; |
---|
1143 | 1169 | } |
---|
.. | .. |
---|
1172 | 1198 | return ret; |
---|
1173 | 1199 | |
---|
1174 | 1200 | ret = clk_prepare_enable(controller->cclk); |
---|
1175 | | - if (ret) |
---|
| 1201 | + if (ret) { |
---|
| 1202 | + clk_disable_unprepare(controller->iclk); |
---|
1176 | 1203 | return ret; |
---|
| 1204 | + } |
---|
1177 | 1205 | |
---|
1178 | 1206 | /* Disable clocks auto gaiting */ |
---|
1179 | 1207 | config = readl_relaxed(controller->base + QUP_CONFIG); |
---|
.. | .. |
---|
1219 | 1247 | return ret; |
---|
1220 | 1248 | |
---|
1221 | 1249 | ret = clk_prepare_enable(controller->cclk); |
---|
1222 | | - if (ret) |
---|
| 1250 | + if (ret) { |
---|
| 1251 | + clk_disable_unprepare(controller->iclk); |
---|
1223 | 1252 | return ret; |
---|
| 1253 | + } |
---|
1224 | 1254 | |
---|
1225 | 1255 | ret = spi_qup_set_state(controller, QUP_STATE_RESET); |
---|
1226 | 1256 | if (ret) |
---|
1227 | | - return ret; |
---|
| 1257 | + goto disable_clk; |
---|
1228 | 1258 | |
---|
1229 | | - return spi_master_resume(master); |
---|
| 1259 | + ret = spi_master_resume(master); |
---|
| 1260 | + if (ret) |
---|
| 1261 | + goto disable_clk; |
---|
| 1262 | + |
---|
| 1263 | + return 0; |
---|
| 1264 | + |
---|
| 1265 | +disable_clk: |
---|
| 1266 | + clk_disable_unprepare(controller->cclk); |
---|
| 1267 | + clk_disable_unprepare(controller->iclk); |
---|
| 1268 | + return ret; |
---|
1230 | 1269 | } |
---|
1231 | 1270 | #endif /* CONFIG_PM_SLEEP */ |
---|
1232 | 1271 | |
---|
.. | .. |
---|
1237 | 1276 | int ret; |
---|
1238 | 1277 | |
---|
1239 | 1278 | ret = pm_runtime_get_sync(&pdev->dev); |
---|
1240 | | - if (ret < 0) |
---|
1241 | | - return ret; |
---|
1242 | 1279 | |
---|
1243 | | - ret = spi_qup_set_state(controller, QUP_STATE_RESET); |
---|
1244 | | - if (ret) |
---|
1245 | | - return ret; |
---|
| 1280 | + if (ret >= 0) { |
---|
| 1281 | + ret = spi_qup_set_state(controller, QUP_STATE_RESET); |
---|
| 1282 | + if (ret) |
---|
| 1283 | + dev_warn(&pdev->dev, "failed to reset controller (%pe)\n", |
---|
| 1284 | + ERR_PTR(ret)); |
---|
| 1285 | + |
---|
| 1286 | + clk_disable_unprepare(controller->cclk); |
---|
| 1287 | + clk_disable_unprepare(controller->iclk); |
---|
| 1288 | + } else { |
---|
| 1289 | + dev_warn(&pdev->dev, "failed to resume, skip hw disable (%pe)\n", |
---|
| 1290 | + ERR_PTR(ret)); |
---|
| 1291 | + } |
---|
1246 | 1292 | |
---|
1247 | 1293 | spi_qup_release_dma(master); |
---|
1248 | | - |
---|
1249 | | - clk_disable_unprepare(controller->cclk); |
---|
1250 | | - clk_disable_unprepare(controller->iclk); |
---|
1251 | 1294 | |
---|
1252 | 1295 | pm_runtime_put_noidle(&pdev->dev); |
---|
1253 | 1296 | pm_runtime_disable(&pdev->dev); |
---|